//
//  This file is part of a five file concatenation of the CwlViews
//  framework with internal interfaces for source inclusion in projects instead
//  of library inclusion.
//  For details, visit: https://github.com/mattgallagher/CwlViews
//
//  Copyright © 2015-2017 Matt Gallagher ( http://cocoawithlove.com ). All rights reserved.
//
//  Permission to use, copy, modify, and/or distribute this software for any
//  purpose with or without fee is hereby granted, provided that the above
//  copyright notice and this permission notice appear in all copies.
//
//  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
//  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
//  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
//  SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
//  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
//  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
//  IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
//  This file was generated by the CwlUtilsConcat tool on 2018-03-17 06:51:18 +0000 from the following files:
//
//    CwlArrayMutation.swift
//    CwlScopedValues.swift
//    CwlBindingName.swift
//    CwlStackMutation.swift
//    CwlStateContainer.swift
//    CwlBinder.swift
//    CwlTargetAction.swift
//    CwlSetMutation.swift
//    CwlFilteredAdapter.swift
//    CwlObjectStorage.swift
//    CwlArrayMutationUtilities.swift
//    CwlCoder.swift
//    CwlStateAdapter.swift
//    CwlBinderPreparer.swift
//    CwlDynamicValue.swift
//    CwlStackAdapter.swift
//    CwlLayout.swift
//

#if os(macOS)
import AppKit
#else
import UIKit
#endif

// MARK: ### CwlArrayMutation.swift ###

/// This enum is intended to be embedded in an ArrayMutation<Value>. The ArrayMutation<Value> combines an IndexSet with this enum. This enum specifies what actions should be taken at the locations specified by the IndexSet.
///
/// 
enum ArrayMutationKind {
	/// The values at the locations specified by the IndexSet should be deleted.
	/// NOTE: the IndexSet specifies the indexes *before* deletion (and must therefore be applied in reverse).
	case delete

	/// The associated Array<Value> contains values that should be inserted such that they have the indexes specified in IndexSet. The Array<Value> and IndexSet must have identical counts.
	/// NOTE: the IndexSet specifies the indexes *after* insertion (and must therefore be applied in forward order).
	case insert

	/// Values are deleted from one end and inserted onto the other. If `Int` is positive, values are deleted from the `startIndex` end and inserted at the `endIndex` end, if `Int` is negative, value are deleted from the `endIndex` end and inserted at the `startIndex`end.
	/// The magnitude of `Int` specifies the number of deleted rows and the sign specified the end.
	/// The Array<Value> contains values that should be inserted at the other end of the collection.
	/// The IndexSet contains the indexes of any revealed (scrolled into view) rows
	case scroll(Int)

	/// The associated Array<Value> contains updated values at locations specified by the IndexSet. Semantically, the item should be modelled as updated but not replaced. The Array<Value> and IndexSet must have identical counts.
	// In many cases, update and replace are the same. The only differences relate to scenarios where the items are considered to have "identity". An update *retains* the previous identity whereas a replace *discards* any previous identity.
	case update
	
	/// The values at the locations specified by the IndexSet should be removed from their locations and spliced back in at the location specified by the associated Int index. For scrolled subranges, items may not be moved from outside or to outside the visible range (items moved from outside the visible range must be inserted and items moved outside the visible range must be deleted)
	/// NOTE: the IndexSet specifies the indexes *before* removal (and must therefore be applied in reverse) and the Int index specifies an index *after* removal.
	case move(Int)

	/// Equivalent to a Deletion of all previous indexes and an Insertion of the new values. The associated Array<Value> contains the new state of the array. All previous values should be discarded and the entire array replaced with this new version. The Array<Value> and IndexSet must have identical counts.
	/// NOTE: the IndexSet specifies the indexes *after* insertion (and must therefore be applied in forward order).
	case reload
}

/// An `ArrayMutation` communicates changes to an array in one context so that another array, mirroring its contents in another context, can mimic the same changes.
/// Subscribing to a stream of `ArrayMutation`s is sufficient to communication the complete state and animatable transitions of an array between to parts of a program.
/// In most cases, the source and destination will need to keep their own complete copy of the array to correctly calculate the effect of the mutation.
struct ArrayMutation<Value>: ExpressibleByArrayLiteral {
	/// Determines the meaning of this `ArrayMutation`
	let kind: ArrayMutationKind

	/// The meaning of the indexSet is dependent on the `kind` – it may contain indexes in the array that will be deleted by this mutation or it may contain indexes that new entries will occupy after application of this mutation.
	let indexSet: IndexSet
	
	/// New values that will be inserted at locations determined by the `kind` and the `indexSet`.
	let values: Array<Value>
	
	/// Construct an empty array mutation that represents a no-op.
	init() {
		self.kind = .update
		self.indexSet = IndexSet()
		self.values = []
	}
	
	/// Construct from components.
	init<S>(indexSet: IndexSet, kind: ArrayMutationKind, values: S) where S: Sequence, S.Element == Value {
		self.kind = kind
		self.indexSet = indexSet
		self.values = Array(values)
	}
	
	/// Construct a mutation that represents the deletion of the values at a set of indices.
	init(deletedIndexSet: IndexSet) {
		self.kind = .delete
		self.indexSet = deletedIndexSet
		self.values = []
	}
	
	/// Construct a mutation that represents the deletion of a value at an index.
	init(deletedIndex: Int) {
		self.kind = .delete
		self.indexSet = IndexSet(integer: deletedIndex)
		self.values = []
	}
	
	/// Construct a mutation that represents the deletion of a value at an index.
	static func deleted(at index: Int) -> ArrayMutation<Value> {
		return ArrayMutation(deletedIndex: index)
	}
	
	/// Construct a mutation that represents the deletion of the values within a range indices.
	init(deletedRange: CountableRange<Int>) {
		self.kind = .delete
		self.indexSet = IndexSet(integersIn: deletedRange)
		self.values = []
	}
	
	/// Construct a mutation that represents the deletion of a value at an index.
	init<S>(scrollForwardRevealing indexSet: IndexSet, values: S) where S: Sequence, S.Element == Value {
		let array = Array(values)
		assert(indexSet.count == array.count)
		self.kind = .scroll(indexSet.count)
		self.indexSet = indexSet
		self.values = Array(array)
	}
	
	/// Construct a mutation that represents the deletion of a value at an index.
	init<S>(scrollBackwardRevealing indexSet: IndexSet, values: S) where S: Sequence, S.Element == Value {
		let array = Array(values)
		assert(indexSet.count == array.count)
		self.kind = .scroll(-indexSet.count)
		self.indexSet = indexSet
		self.values = array
	}
	
	/// Construct a mutation that represents the insertion of a number of values at a set of indices. The count of indices must match the count of values.
	init<S>(insertedIndexSet: IndexSet, values: S) where S: Sequence, S.Element == Value {
		let array = Array(values)
		assert(insertedIndexSet.count == array.count)
		self.kind = .insert
		self.indexSet = insertedIndexSet
		self.values = array
	}
	
	/// Construct a mutation that represents the insertion of a value at an index.
	init(insertedIndex: Int, value: Value) {
		self.kind = .insert
		self.indexSet = IndexSet(integer: insertedIndex)
		self.values = [value]
	}

	/// Construct a mutation that represents the insertion of a number of values within a range of indices. The count of the range must match the count of values.
	init<S>(insertedRange: CountableRange<Int>, values: S) where S: Sequence, S.Element == Value {
		let array = Array(values)
		assert(insertedRange.count == array.count)
		self.kind = .insert
		self.indexSet = IndexSet(integersIn: insertedRange)
		self.values = array
	}
	
	/// Construct a mutation that discards any previous history and simply starts with a completely new array.
	init<S>(reload values: S) where S: Sequence, S.Element == Value {
		let array = Array(values)
		self.kind = .reload
		self.indexSet = IndexSet(integersIn: array.indices)
		self.values = array
	}
	
	/// A .Reload mutation can be constructed from an array literal (since it is equivalent to an array assignment).
	init(arrayLiteral elements: Value...) {
		self.init(reload: elements)
	}
	
	/// Construct a mutation that represents the update of a number of values at a set of indices. The count of indices must match the count of values.
	init<S>(updatedIndexSet: IndexSet, values: S) where S: Sequence, S.Element == Value {
		let array = Array(values)
		assert(updatedIndexSet.count == array.count)
		self.kind = .update
		self.indexSet = updatedIndexSet
		self.values = array
	}
	
	/// Construct a mutation that represents the update of a value at an index.
	init(updatedIndex: Int, value: Value) {
		self.kind = .update
		self.indexSet = IndexSet(integer: updatedIndex)
		self.values = [value]
	}
	
	/// Construct a mutation that represents the udpate of a number of values within a range of indices. The count of the range must match the count of values.
	init<S>(updatedRange: CountableRange<Int>, values: S) where S: Sequence, S.Element == Value {
		let array = Array(values)
		assert(updatedRange.count == array.count)
		self.kind = .update
		self.indexSet = IndexSet(integersIn: updatedRange)
		self.values = array
	}
	
	/// Construct a mutation that represents the move of a number of values from a set of indices to a new range starting at targetIndex. NOTE: the order of values once inserted at targetIndex must be the same as the order in movedIndexSet.
	init(movedIndexSet: IndexSet, targetIndex: Int) {
		self.kind = .move(targetIndex)
		self.indexSet = movedIndexSet
		self.values = []
	}

	/// Construct a mutation that represents the move of a value at movedIndex to a new range starting at targetIndex.
	init(movedIndex: Int, targetIndex: Int) {
		self.kind = .move(targetIndex)
		self.indexSet = IndexSet(integer: movedIndex)
		self.values = []
	}

	/// Construct a mutation that represents the move of a range of values to a new range starting at targetIndex. NOTE: the order of values once inserted at targetIndex must be the same as the order in movedRange.
	init(movedRange: CountableRange<Int>, targetIndex: Int) {
		self.kind = .move(targetIndex)
		self.indexSet = IndexSet(integersIn: movedRange)
		self.values = []
	}

	/// Apply the mutation described by this value to the provided array
	func apply<C: RangeReplaceableCollection>(to a: inout C) where C.Index == Int, C.Iterator.Element == Value {
		switch kind {
		case .delete:
			indexSet.rangeView.reversed().forEach { a.removeSubrange($0) }
		case .scroll(let offset):
			a.removeSubrange(offset > 0 ? a.startIndex..<offset : (a.endIndex + offset)..<a.endIndex)
			a.insert(contentsOf: values, at: offset > 0 ? a.endIndex : a.startIndex)
		case .move(let index):
			let moving = indexSet.map { a[$0] }
			indexSet.rangeView.reversed().forEach { a.removeSubrange($0) }
			a.insert(contentsOf: moving, at: index)
		case .insert:
			for (i, v) in zip(indexSet, values) {
				a.insert(v, at: i)
			}
		case .update:
			for (i, v) in zip(indexSet, values) {
				a.insert(v, at: i)
			}
		case .reload:
			a.replaceSubrange(a.startIndex..<a.endIndex, with: values)
		}
	}
	
	func map<Other>(_ transform: (Value) -> Other) -> ArrayMutation<Other> {
		return ArrayMutation<Other>(indexSet: indexSet, kind: kind, values: values.map(transform))
	}
	
	func removed(previousIndices a: CountableRange<Int>) -> IndexSet {
		switch kind {
		case .delete: return indexSet
		case .scroll(let offset): return IndexSet(integersIn: offset > 0 ? (a.endIndex - offset)..<a.endIndex : a.startIndex..<(a.startIndex + offset))
		case .reload: return IndexSet(integersIn: a)
		case .move: fallthrough
		case .insert: fallthrough
		case .update: return IndexSet()
		}
	}
	
	func inserted(subsequentIndices a: CountableRange<Int>) -> IndexSet {
		switch kind {
		case .insert: return indexSet
		case .scroll(let offset): return IndexSet(integersIn: offset > 0 ? a.startIndex..<offset : (a.endIndex + offset)..<a.endIndex)
		case .reload: return IndexSet(integersIn: a)
		case .delete: return indexSet
		case .move: fallthrough
		case .update: return IndexSet()
		}
	}
	
	/// Updates a row count due to this mutation.
	func delta(_ rowCount: inout Int) {
		switch kind {
		case .reload: rowCount = values.count
		case .delete: rowCount -= indexSet.count
		case .scroll(let offset): rowCount += values.count - (offset > 0 ? offset : -offset)
		case .insert: rowCount += values.count
		case .move: return
		case .update: return
		}
	}
}

// MARK: ### CwlScopedValues.swift ###

import Foundation

struct ScopedValues<Scope, Value>: ExpressibleByArrayLiteral {
	typealias ArrayLiteralElement = ScopedValues<Scope, Value>
	init(arrayLiteral elements: ScopedValues<Scope, Value>...) {
		self.pairs = elements.flatMap { $0.pairs }
	}
	
	let pairs: [(scope: Scope, value: Value)]
	init(pairs: (Scope, Value)...) {
		self.pairs = pairs
	}
	init(pairs: [(Scope, Value)]) {
		self.pairs = pairs
	}
	init(scope: Scope, value: Value) {
		self.pairs = [(scope, value)]
	}
	static func value(_ value: Value, for scope: Scope) -> ScopedValues<Scope, Value> {
		return ScopedValues(scope: scope, value: value)
	}
}

// MARK: ### CwlBindingName.swift ###

infix operator --: AssignmentPrecedence
infix operator <--: AssignmentPrecedence
infix operator -->: AssignmentPrecedence

struct BindingName<Value, Binding> {
	var constructor: (Value) -> Binding
	init(_ constructor: @escaping (Value) -> Binding) {
		self.constructor = constructor
	}

	static func <--<Interface: SignalInterface>(name: BindingName<Value, Binding>, value: Interface) -> Binding where Signal<Interface.OutputValue> == Value {
		return name.constructor(value.signal)
	}

	static func <--<Interface: SignalInterface>(name: BindingName<Value, Binding>, value: Interface) -> Binding where DynamicValue<Interface.OutputValue> == Value {
		return name.constructor(DynamicValue<Interface.OutputValue>.fromDynamic(value.signal))
	}

	static func --><InputInterface: SignalInputInterface>(name: BindingName<Value, Binding>, value: InputInterface) -> Binding where SignalInput<InputInterface.InputValue> == Value {
		return name.constructor(value.input)
	}

	static func --><InputInterface: SignalInputInterface>(name: BindingName<Value, Binding>, value: InputInterface) -> Binding where TargetAction<InputInterface.InputValue> == Value {
		return name.constructor(.singleTarget(value.input))
	}
	
	static func --<A>(name: BindingName<Value, Binding>, value: A) -> Binding where Value == StaticValue<A> {
		return name.constructor(Value.fromConstant(value))
	}

	static func --<A>(name: BindingName<Value, Binding>, value: A) -> Binding where DynamicValue<A> == Value {
		return name.constructor(DynamicValue<A>.fromConstant(value))
	}

	static func --<R>(name: BindingName<Value, Binding>, value: @escaping () -> R) -> Binding where Value == () -> R {
		return name.constructor(value)
	}

	static func --<A, R>(name: BindingName<Value, Binding>, value: @escaping (A) -> R) -> Binding where Value == (A) -> R {
		return name.constructor(value)
	}

	static func --<A, B, R>(name: BindingName<Value, Binding>, value: @escaping (A, B) -> R) -> Binding where Value == (A, B) -> R {
		return name.constructor(value)
	}

	static func --<A, B, C, R>(name: BindingName<Value, Binding>, value: @escaping (A, B, C) -> R) -> Binding where Value == (A, B, C) -> R {
		return name.constructor(value)
	}

	static func --<A, B, C, D, R>(name: BindingName<Value, Binding>, value: @escaping (A, B, C, D) -> R) -> Binding where Value == (A, B, C, D) -> R {
		return name.constructor(value)
	}

	static func --<A, B, C, D, E, R>(name: BindingName<Value, Binding>, value: @escaping (A, B, C, D, E) -> R) -> Binding where Value == (A, B, C, D, E) -> R {
		return name.constructor(value)
	}
}

#if os(macOS)
extension BindingName {
	static func --><A>(name: BindingName<TargetAction<A>, Binding>, value: Selector) -> Binding where Value == TargetAction<A> {
		return name.constructor(Value.fromSelector(value))
	}
}
#endif

// MARK: ### CwlStackMutation.swift ###

enum StackMutation<Value>: ExpressibleByArrayLiteral {
	init(arrayLiteral elements: Value...) {
		self = .reload(elements)
	}
	
	typealias ArrayLiteralElement = Value
	
	case push(Value)
	case pop
	case popToCount(Int)
	case reload([Value])
	
	func apply(to stack: inout Array<Value>) {
		switch self {
		case .push(let v): stack.append(v)
		case .pop: stack.removeLast()
		case .popToCount(let c): stack.removeLast(stack.count - c)
		case .reload(let newStack): stack = newStack
		}
	}
}

extension SignalInterface {
	func stackMap<A, B>(_ transform: @escaping (A) -> B) -> Signal<StackMutation<B>> where OutputValue == StackMutation<A> {
		return map { m in
			switch m {
				case .push(let a): return StackMutation<B>.push(transform(a))
				case .pop: return StackMutation<B>.pop
				case .popToCount(let i): return StackMutation<B>.popToCount(i)
				case .reload(let array): return StackMutation<B>.reload(array.map { transform($0) })
			}
		}
	}
}

// MARK: ### CwlStateContainer.swift ###

protocol StateContainer: Cancellable, Codable {
	var persistentValueChanged: Signal<()> { get }
	var childValues: [StateContainer] { get }
}

extension StateContainer {
	var childValues: [StateContainer] { return [] }
	var persistentValueChanged: Signal<()> {
		return Signal<()>.merge(childValues.map {
			return $0.persistentValueChanged
		})
	}
	func cancel() {
		childValues.forEach { $0.cancel() }
	}
}

extension Array: Cancellable where Element: Cancellable {
	mutating func cancel() {
		for var v in self {
			v.cancel()
		}
	}
}

extension Array: StateContainer where Element: StateContainer {
	var childValues: [StateContainer] {
		return self.map { $0 as StateContainer }
	}
}

extension Optional: StateContainer where Wrapped: StateContainer {
	var childValues: [StateContainer] {
		guard let s = self else { return [] }
		return [s]
	}
}

// MARK: ### CwlBinder.swift ###

#if os(macOS)
	import Cocoa
#elseif os(iOS)
	import UIKit
#endif

protocol BaseBinding {
	associatedtype Binder = DerivedBinder
	static func baseBinderBinding(_ binding: BaseBinder.Binding) -> Self
}

protocol BinderChain {
	associatedtype Inherited
	associatedtype Instance
	associatedtype Storage
	associatedtype Binding
	associatedtype Preparer
}

protocol DerivedBinder: class, BinderChain where Preparer: BinderPreparer, Binding: BaseBinding, Storage: BinderStorage, Inherited: BinderChain, Inherited.Preparer: BinderPreparer, Inherited.Binding: BaseBinding {
	static func bindingToInherited(_ binding: Binding) -> Inherited.Binding?
	
	func applyBindings(to instance: Instance)
	func consumeBindings() -> [Binding]
}

struct BinderParameters<Instance, Binding> {
	let subclass: Instance.Type
	let bindings: [Binding]
	init(subclass: Instance.Type, bindings: [Binding]) {
		self.subclass = subclass
		self.bindings = bindings
	}
}

typealias BinderConstructionState<Instance, Binding> = BinderState<Instance, BinderParameters<Instance, Binding>>

enum BinderState<Instance, Parameters> {
	case constructed(Instance)
	case pending(Parameters)
	case consumed
	
	mutating func consume() -> Parameters {
		switch self {
		case .pending(let p): return p
		default: fatalError("Attempt to consume already consumed bindings")
		}
	}
	
	mutating func construct(handle: (Parameters) -> Instance) -> Instance {
		switch self {
		case .constructed(let i): return i
		case .pending(let p):
			self = .consumed
			let instance = handle(p)
			self = .constructed(instance)
			return instance
		default: fatalError("Attempt to apply already consumed bindings")
		}
	}

	mutating func apply(instance: Instance, handle: (Instance, Parameters) -> ()) {
		switch self {
		case .pending(let p):
			self = .consumed
			handle(instance, p)
		default: fatalError("Attempt to apply already consumed bindings")
		}
	}
}

protocol ConstructingBinder: DerivedBinder {
	var state: BinderConstructionState<Instance, Binding> { get set }
	init(subclass: Instance.Type, bindings: [Binding])
	func instance(additional: ((Instance) -> Cancellable?)?) -> Instance
}

extension ConstructingBinder where Preparer: ConstructingPreparer, Instance: NSObject, Binding.Binder == Self, Inherited.Binding.Binder == Inherited, Preparer.Binder == Self, Inherited.Preparer.Binder == Inherited {
	init(subclass: Instance.Type = Instance.self, _ bindings: Binding...) {
		self.init(subclass: subclass, bindings: bindings)
	}
	
	func consumeBindings() -> [Binding] {
		return state.consume().bindings
	}

	func applyBindings(to instance: Instance) {
		state.apply(instance: instance) { i, parameters in
			_ = Preparer.construct(bindings: parameters.bindings, additional: nil, storageConstructor: { $0.constructStorage() }, instanceConstructor: { _ in i })
		}
	}
	
	func instance(additional: ((Instance) -> Cancellable?)? = nil) -> Instance {
		return state.construct { parameters in
			Preparer.construct(bindings: parameters.bindings, additional: additional, storageConstructor: { $0.constructStorage() }, instanceConstructor: { $0.constructInstance(subclass: parameters.subclass) })
		}
	}
}

struct BaseBinder: BinderChain {
	typealias Instance = Any
	typealias Storage = Any
	typealias Inherited = ()

	enum Binding: BaseBinding {
		typealias Binder = BaseBinder
		static func baseBinderBinding(_ binding: Binding) -> Binding { return binding }

		/// Each value in the cancelOnClose will be cancelled when the `Storage` is released. This is guaranteed to be invoked on the main thread (if `Storage` is released on a non-main thread, the effect will occur asynchronously on the main thread).
		case cancelOnClose(DynamicValue<[Cancellable]>)
	}

	struct Preparer: BinderPreparer {
		typealias Binder = BaseBinder

		init() {}
		var linkedPreparer: () {
			get { return () }
			set { }
		}
		mutating func prepareBinding(_ binding: Binding) {}
		mutating func prepareInstance(_ instance: Instance, storage: Storage) {}
		mutating func finalizeInstance(_ instance: Instance, storage: Storage) -> Cancellable? { return nil }
		func applyBinding(_ binding: Binding, instance: Instance, storage: Storage) -> Cancellable? {
			switch binding {
			case .cancelOnClose(let x):
				switch x {
				case .constant(let array): return ArrayOfCancellables(array)
				case .dynamic(let signal): return signal.continuous().subscribe { r in }
				}
			}
		}
	}
}

extension BindingName where Binding: BaseBinding {
	// You can easily convert the `Binding` cases to `BindingName` using the following Xcode-style regex:
	// Replace: case ([^\(]+)\((.+)\)$
	// With:    static var $1: BindingName<$2, Binding> { return BindingName<$2, Binding>({ v in .baseBinderBinding(BaseBinder.Binding.$1(v)) }) }
	static var cancelOnClose: BindingName<DynamicValue<[Cancellable]>, Binding> { return BindingName<DynamicValue<[Cancellable]>, Binding>({ v in .baseBinderBinding(BaseBinder.Binding.cancelOnClose(v)) }) }
}

protocol BinderStorage: class, Cancellable {
	/// The `BinderStorage` needs to maintain the lifetime of all the self-managing objects, the most common of which are `Signal` and `SignalInput` instances but others may include `DispatchSourceTimer`. Most of these objects implement `Cancellable` so maintaining their lifetime is as simple as retaining these `Cancellable` instances in an array.
	/// The `bindings` array should be set precisely once, at the end of construction and an assertion may be raised if subsequent mutations are attempted.
	func setCancellables(_ cancellables: [Cancellable])
	
	/// Since the `BinderStorage` object is a supporting instance for the stateful object and exists to manage interactions but it is possible that the stateful object is constructed without the intention of mutation or interaction – in which case, the `BinderStorage` is not needed. The `inUse` getter is provided to ask if the `BinderStorage` is really necessary (a result of `true` may result in the `BinderStorage` being immediately discarded).
	var inUse: Bool { get }
}

// MARK: ### CwlTargetAction.swift ###

/// This type encapsulates the idea that target-action pairs in Cocoa may target a specific object (by setting the target to non-nil) or may let the responder chain search (for a responder that handles a give selector).
/// On the Mac, this might encapsulate the entire semantics of target-action. On iOS, we usually need to know which `UIControlEvents` are desired so the `TargetActionForControlEvents` type wraps this type and includes a `controlEvents` property too.
enum TargetAction<Value> {
	typealias ValueType = Value
	case firstResponder(Selector)
	case singleTarget(SignalInput<Value>)
	static func fromSelector(_ selector: Selector) -> TargetAction<Value> {
		return .firstResponder(selector)
	}
	static func fromSingleTarget(_ input: SignalInput<ValueType>) -> TargetAction<Value> {
		return .singleTarget(input)
	}
}

protocol TargetActionSender: class {
	var action: Selector? { get set }
	var target: AnyObject? { get set }
}

extension TargetAction {
	func apply<U: TargetActionSender>(instance: U, constructTarget: () -> SignalActionTarget, processor: @escaping (Any?) -> Value) -> Cancellable? {
		switch self {
		case .firstResponder(let s):
			instance.target = nil
			instance.action = s
			return nil
		case .singleTarget(let s):
			let target = constructTarget()
			instance.target = target
			instance.action = target.selector
			return target.signal.map(processor).cancellableBind(to: s)
		}
	}
}

// MARK: ### CwlSetMutation.swift ###

import Foundation

enum SetMutationKind {
	case delete
	case insert
	case update
	case reload
}

struct SetMutation<Element> {
	let kind: SetMutationKind
	let values: Array<Element>
	
	init(kind: SetMutationKind, values: Array<Element>) {
		self.kind = kind
		self.values = values
	}
	
	static func delete(_ values: Array<Element>) -> SetMutation<Element> {
		return SetMutation(kind: .delete, values: values)
	}
	
	static func insert(_ values: Array<Element>) -> SetMutation<Element> {
		return SetMutation(kind: .insert, values: values)
	}
	
	static func update(_ values: Array<Element>) -> SetMutation<Element> {
		return SetMutation(kind: .update, values: values)
	}
	
	static func reload(_ values: Array<Element>) -> SetMutation<Element> {
		return SetMutation(kind: .reload, values: values)
	}
	
	func apply(to array: inout Array<Element>, equate: @escaping (Element, Element) -> Bool, compare: @escaping (Element, Element) -> Bool) -> [ArrayMutation<Element>] {
		switch kind {
		case .delete:
			var sorted = values.sorted(by: compare)
			var oldIndices = IndexSet()
			var arrayIndex = 0
			var sortedIndex = 0
			while arrayIndex < array.count && sortedIndex < sorted.count {
				if !equate(array[arrayIndex], sorted[sortedIndex]) {
					arrayIndex += 1
				} else {
					oldIndices.insert(arrayIndex)
					sortedIndex += 1
					arrayIndex += 1
				}
			}
			precondition(sortedIndex == sorted.count, "Unable to find deleted items.")
			oldIndices.reversed().forEach { array.remove(at: $0) }
			return [ArrayMutation<Element>(deletedIndexSet: oldIndices)]
		case .insert:
			var sorted = values.sorted(by: compare)
			var newIndices = IndexSet()
			var arrayIndex = 0
			var sortedIndex = 0
			while arrayIndex < array.count && sortedIndex < sorted.count {
				if compare(array[arrayIndex], sorted[sortedIndex]) {
					arrayIndex += 1
				} else {
					newIndices.insert(arrayIndex)
					array.insert(sorted[sortedIndex], at: arrayIndex)
					sortedIndex += 1
					arrayIndex += 1
				}
			}
			while sortedIndex < sorted.count {
				newIndices.insert(arrayIndex)
				array.insert(sorted[sortedIndex], at: arrayIndex)
				sortedIndex += 1
				arrayIndex += 1
			}
			return [ArrayMutation<Element>(insertedIndexSet: newIndices, values: sorted)]
		case .update:
			// It would be nice if this was better than n squared complexity and aggregated the updates, rather than issueing updates for individual rows.
			var result = Array<ArrayMutation<Element>>()
			for v in values {
				let oldIndex = array.index { u in equate(v, u) }!
				array.remove(at: oldIndex)
				let newIndex = array.index { u in compare(v, u) } ?? array.count
				array.insert(v, at: newIndex)
				if newIndex == oldIndex {
					result.append(.updated(v, at: oldIndex))
				} else {
					// This ordering (moved, then updated) is required to make UITableView animations work correctly.
					result.append(.moved(from: oldIndex, to: newIndex))
					result.append(.updated(v, at: newIndex))
				}
			}
			return result
		case .reload:
			array = values.sorted(by: compare)
			return [ArrayMutation<Element>(reload: array)]
		}
	}
}

extension SignalInterface {
	func sortedArrayMutation<Element>(equate: @escaping (Element, Element) -> Bool, compare: @escaping (Element, Element) -> Bool) -> Signal<ArrayMutation<Element>> where SetMutation<Element> == OutputValue {
		return transform(initialState: Array<Element>()) { (array: inout Array<Element>, result: Result<SetMutation<Element>>, next: SignalNext<ArrayMutation<Element>>) in
			switch result {
			case .success(let mutation):
				mutation.apply(to: &array, equate: equate, compare: compare).forEach { next.send(value: $0) }
			case .failure(let e): next.send(error: e)
			}
		}
	}
}

// MARK: ### CwlFilteredAdapter.swift ###

/// Instead of offering a single "notification" output signal, like a plain `StateAdapter`, the `FilteredAdapter` is optimized around the idea of multiple filtered views of the output, with subtle questions like "whether to notify immediately upon connecting" handled by the filtered view, rather than a behavior baked into the adapter.
/// A single shared `State` is shared between the `reducer` and filter stages of the pipeline using a manual synchronization context to ensure this remains threadsafe. The `withMutableState` function offers synchronous, threadsafe access to the same storage for serialization and other concerns that might require immediate access.
/// However, there are also some omissions. Unlike `StateAdapter`, this *requires* an initial `State`. There is also no built-in support for `Codable`, since this `FilteredAdapter` would typically be used on data where serialization and persistence are manually handled.
struct FilteredAdapter<Message, State, Notification>: Cancellable, SignalInputInterface {	
	typealias InputValue = Message
	typealias OutputValue = State
	enum PossibleNotification {
		case never
		case suppress
		case value(Notification)
	}
	
	let pair: SignalMultiPair<Message, PossibleNotification>
	var input: SignalInput<Message> { return pair.input }
	
	private let context: DispatchQueueContext
	private let state: MutableBox<State>
	
	/// Construction where the `reducer` function includes a `loopback` parameter
	///
	/// - Parameters:
	///   - initialState: used to initialize the adapter state
	///   - sync: the adapter's execution context can be synchronous or asychronous but otherwise can't be directly specified (true, by default)
	///   - cacheNotification: the last emitted notification can be cached for new observers (false, by default)
	///   - reducer: the reducing function which combines the internal `State` and `Message` on each iteration, emitting a `Notification?` (or throwing in the case of unrecoverable error or close state). A `loopback` parameter is provided which allows the reducing function to schedule asynchronous tasks that may call back into the adapter at a later time.
	init(initialState: State, sync: Bool = true, cacheNotification: Bool = false, reducer: @escaping (_ state: inout State, _ message: Message, _ loopback: SignalMultiInput<Message>) throws -> Notification?) {
		state = MutableBox<State>(initialState)
		context = DispatchQueueContext(sync: sync)
		let channel = Signal<Message>.multiChannel()
		let loopback = channel.input
		pair = channel.reduce(initialState: .never, context: .custom(context)) { [state, loopback] (cache: inout PossibleNotification, message: Message) -> PossibleNotification in
			let notification = try reducer(&state.value, message, loopback)
			if let n = notification {
				if cacheNotification {
					cache = .value(n)
				}
				return .value(n)
			}
			return .suppress
		}
	}
	
	
	/// Construction where the `reducer` function omits the `loopback` parameter
	///
	/// - Parameters:
	///   - initialState: used to initialize the adapter state
	///   - sync: the adapter's execution context can be synchronous or asychronous but otherwise can't be directly specified (true, by default)
	///   - cacheNotification: the last emitted notification can be cached for new observers (false, by default)
	///   - reducer: the reducing function which combines the internal `State` and `Message` on each iteration, emitting a `Notification?` (or throwing in the case of unrecoverable error or close state).
	init(initialState: State, sync: Bool = true, cacheNotification: Bool = false, reducer: @escaping (_ state: inout State, _ input: Message) throws -> Notification?) {
		self.init(initialState: initialState, sync: sync, cacheNotification: cacheNotification) { (state: inout State, input: Message, collector: SignalMultiInput<Message>) -> Notification? in
			return try reducer(&state, input)
		}
	}
	
	/// Cancels the signal graph (no further actions will be possible).
	func cancel() {
		pair.input.cancel()
	}
	
	/// Filters the `PossibleNotification` output signal down to `Notification`, turning the initial `never` into a value using the provided `initial` function. When `PossibleNotification` is `suppress` (i.e. the last reducer invocation returned `nil`) no notification signal will be emitted.
	///
	/// - Returns: the notificationSignal
	func notificationSignal(initial: @escaping (State) -> Notification? = { _ in nil }) -> Signal<Notification> {
		return pair.signal.compactMap { [state] (possibleNotification: PossibleNotification) in
			switch possibleNotification {
			case .never: return initial(state.value)
			case .suppress: return nil
			case .value(let n): return n
			}
		}
	}
	
	var stateSignal: Signal<State> {
		return pair.signal.compactMap { [state] (possibleNotification: PossibleNotification) -> State? in
			if case .suppress = possibleNotification {
				return nil
			}
			return state.value
		}
	}
	
	/// This is the canonical output of the `FilteredAdapter`. On initial connection and each non-nil returning invocation of the adapter, the `processor` provided to this function is given a chance to produce and emit a slice of the `State` to its listeners.
	///
	/// - initialValue: a context value passed into the processor on each invocation
	/// - processor: the function that produces and emits the slice of `State`. The `State` is provided as an `UnsafePointer`, since Swift doesn't have another way to indicate read-only pass-by-reference. The `Notification?` parameter will be `nil` on initial invocation but will never be `nil` again after that point – this distinction allows construction of a specialized slice on initial connection. Output from the function is via the `SignalNext<Processed>` parameter, allowing zero, one or more value outputs or a close, if desired.
	/// - Returns: the signal output from the `processor`
	func filteredSignal<Value, Processed>(initialValue: Value, _ processor: @escaping (inout Value, State, Notification?, SignalNext<Processed>) throws -> Void) -> Signal<Processed> {
		return pair.signal.transform(initialState: initialValue) { [state] (value: inout Value, incoming: Result<PossibleNotification>, next: SignalNext<Processed>) in
			do {
				switch try incoming.unwrap() {
				case .never: try processor(&value, state.value, nil, next)
				case .suppress: break
				case .value(let n): try processor(&value, state.value, n, next)
				}
			} catch {
				next.send(error: error)
			}
		}
	}
	
	/// Same as `filteredSignal(initialValue:_:)` minus the context value
	///
	/// - processor: the function that produces and emits the slice of `State`. The `State` is provided as an `UnsafePointer`, since Swift doesn't have another way to indicate read-only pass-by-reference. The `Notification?` parameter will be `nil` on initial invocation but will never be `nil` again after that point – this distinction allows construction of a specialized slice on initial connection. Output from the function is via the `SignalNext<Processed>` parameter, allowing zero, one or more value outputs or a close, if desired.
	/// - Returns: the signal output from the `processor`
	func filteredSignal<Processed>(_ processor: @escaping (State, Notification?, SignalNext<Processed>) throws -> Void) -> Signal<Processed> {
		return filteredSignal(initialValue: ()) { (value: inout (), state: State, notification: Notification?, next: SignalNext<Processed>) throws in
			try processor(state, notification, next)
		}
	}
	
	/// Allows out-of-stream access to the `State` (for synchronous actions like save). Since this function acquires the context where the signal closures run, do *not* call this from one of the `filterSignal` or `notificationSignal` processing closures as it will deadlock attempting re-entrant access to the context.
	func withMutableState<Value>(_ perform: (inout State) throws -> Value) rethrows -> Value {
		return try context.queue.sync {
			try perform(&state.value)
		}
	}
}

// MARK: ### CwlObjectStorage.swift ###

/// Implementation for `BinderStorage` that wraps Cocoa objects.
class ObjectBinderStorage: NSObject, BinderStorage {
	fileprivate var cancellables: [Cancellable]? = nil
	func setCancellables(_ cancellables: [Cancellable]) {
		assert(self.cancellables == nil, "Bindings should be set once only")
		self.cancellables = cancellables
	}
	
	// An `ObjectBinderStorage` is an "internal" object but we don't need to keep it around if it isn't in-use. By default, that means: are we using the object for binding or delegation. Subclasses that store additional properties or implement delegate methods directly (without forwarding to the dynamic delegate) must override this with additional logic.
	var inUse: Bool {
		return cancellables?.isEmpty == false || dynamicDelegate != nil
	}
	
	/// Explicitly invoke `cancel` on each of the bindings.
	///
	/// WARNING: if `cancel` is invoked outside the main thread, it will be *asynchronously* invoked on the main thread.
	/// Normally, a `cancel` effect is expected to have synchronous effect but it since `cancel` on Binder objects is usually used for breaking reference counted loops, it is considered that the synchronous effect of cancel is less important than avoiding deadlocks – and deadlocks would be easy to accidentally trigger if this were synchronously invoked. If you need synchronous effect, ensure that cancel is invoked on the main thread.
	func cancel() {
		if let cs = cancellables {
			if Thread.isMainThread {
				// `cancel` is mutating so we must use a `for var` (we can't use `forEach`)
				for var c in cs {
					c.cancel()
				}
			} else {
				DispatchQueue.main.sync {
					// `cancel` is mutating so we must use a `for var` (we can't use `forEach`)
					for var c in cs {
						c.cancel()
					}
				}
			}
			cancellables?.removeAll()
		}
	}
	
	deinit {
		cancel()
	}
	
	/// The `dynamicDelegate` is a work-around for the fact that some Cocoa objects change their behavior if you have a delegate that implements a given delegate method. Since Binders will likely implement *all* of their delegate methods, the dynamicDelegate can be used to selectively respond to particular selectors at runtime.
	var dynamicDelegate: DynamicDelegate?
	
	/// An override of the NSObject method so that the dynamicDelegate can work. When the dynamicDelegate states that it can respond to a given selector, that selector is directed to the dynamicDelegate instead. This function will only be involved if Objective-C message sends are sent to the BinderStorage – a rare occurrence outside of deliberate delegate invocations.
	///
	/// - Parameter selector: Objective-C selector that may be implemented by the dynamicDelegate
	/// - Returns: the dynamicDelegate, if it implements the selector
	override func forwardingTarget(for selector: Selector) -> Any? {
		if let dd = dynamicDelegate, dd.implementedSelectors.contains(selector) {
			return dd
		}
		return nil
	}
	
	/// An override of the NSObject method so that the dynamicDelegate can work.
	///
	/// - Parameter selector: Objective-C selector that may be implemented by the dynamicDelegate
	/// - Returns: true if the dynamicDelegate implements the selector, otherwise returns the super implementation
	override func responds(to selector: Selector) -> Bool {
		if let dd = dynamicDelegate, dd.implementedSelectors.contains(selector) {
			return true
		}
		return super.responds(to: selector)
	}
}

/// Used in conjunction with `ObjectBinderStorage`, subclasses of `DynamicDelegate` can implement all delegate methods at compile time but have the `ObjectBinderStorage` report true to `responds(to:)` only in the cases where the delegate method is selected for enabling.
class DynamicDelegate: NSObject, Cancellable {
	var implementedSelectors = Set<Selector>()
	
	@discardableResult
	func addSelector(_ selector: Selector) -> Self {
		implementedSelectors.insert(selector)
		return self
	}
	
	func cancel() {
		implementedSelectors = []
	}
}


/// Most objects managed by a `BinderStorage` are Objective-C objects (`NSView`/`UIView`, `NSApplication`/`UIApplication`, etc). For these objects, we can satisfy the requirement of tying the stateful and binder objects together by storing the binder in the Objective-C "associated object" storage.
private var associatedStorageKey = NSObject()
extension NSObject {
	func setBinderStorage(_ newValue: BinderStorage?) {
		objc_setAssociatedObject(self, &associatedStorageKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
	}
	func getBinderStorage<T: BinderStorage>(type: T.Type) -> T? {
		return objc_getAssociatedObject(self, &associatedStorageKey) as? T
	}
}

func embedStorageIfInUse<Storage: BinderStorage>(_ instance: NSObject, _ storage: Storage, _ cancellables: [Cancellable]) {
	storage.setCancellables(cancellables)
	if storage.inUse {
		instance.setBinderStorage(storage)
	}
}

func embedStorageIfInUse<Instance: NSObject, Storage: BinderStorage>(afterAdding: @escaping (Instance) -> Cancellable?) -> (Instance, Storage, [Cancellable]) -> Void {
	return { (instance: Instance, storage: Storage, cancellables: [Cancellable]) in
		var appendedCancellables = cancellables
		if let c = afterAdding(instance) {
			appendedCancellables += c
		}
		embedStorageIfInUse(instance, storage, appendedCancellables)
	}
}

// MARK: ### CwlArrayMutationUtilities.swift ###

import Foundation

extension Sequence {
	func arrayMutation() -> ArrayMutation<Element> {
		return .reload(self)
	}
	
	func rowMutation() -> TableRowMutation<Element> {
		return TableRowMutation(arrayMutation: arrayMutation())
	}
	
	func sectionMutation(header: String? = nil, footer: String? = nil) -> TableSectionMutation<Element> {
		return rowMutation().sectionMutation(header: header, footer: footer)
	}
	
	func tableData(header: String? = nil, footer: String? = nil) -> TableData<Element> {
		return rowMutation().sectionMutation(header: header, footer: footer).tableData()
	}
}

extension ArrayMutation {
	/// Construct a mutation that represents the insertion of a value at an index.
	static func inserted(_ value: Value, at index: Int) -> ArrayMutation<Value> {
		return ArrayMutation(insertedIndex: index, value: value)
	}

	/// Construct a mutation that discards any previous history and simply starts with a completely new array.
	static func reload<S: Sequence>(_ values: S) -> ArrayMutation<Value> where S.Element == Value {
		return ArrayMutation(reload: Array(values))
	}

	/// Construct a mutation that represents the update of a value at an index.
	static func updated(_ value: Value, at index: Int) -> ArrayMutation<Value> {
		return ArrayMutation(updatedIndex: index, value: value)
	}

	/// Construct a mutation that represents the update of a value at an index.
	static func moved(from sourceIndex: Int, to targetIndex: Int) -> ArrayMutation<Value> {
		return ArrayMutation(movedIndex: sourceIndex, targetIndex: targetIndex)
	}
	
	func rowMutation() -> TableRowMutation<Value> {
		return TableRowMutation(arrayMutation: self)
	}
	
	func sectionMutation(header: String? = nil, footer: String? = nil) -> TableSectionMutation<Value> {
		return rowMutation().sectionMutation(header: header, footer: footer)
	}
	
	func tableData(header: String? = nil, footer: String? = nil) -> TableData<Value> {
		return rowMutation().sectionMutation(header: header, footer: footer).tableData()
	}
}

extension TableRowMutation {
	func sectionMutation(header: String? = nil, footer: String? = nil) -> TableSectionMutation<Value> {
		return TableSectionMutation(header: header, footer: footer, rowMutation: self)
	}
	
	func tableData(header: String? = nil, footer: String? = nil) -> TableData<Value> {
		return sectionMutation(header: header, footer: footer).tableData()
	}
}

extension TableSectionMutation {
	func tableData() -> TableRowMutation<TableSectionMutation<Value>> {
		return TableRowMutation(array: [self])
	}
}

extension TableRowMutation {
	static func tableData<RowData>(sections: [TableSectionMutation<RowData>]) -> TableData<RowData> where TableSectionMutation<RowData> == Value {
		return TableRowMutation(array: sections)
	}

	static func tableDataFromSections<RowData>(_ sections: TableSectionMutation<RowData>...) -> TableData<RowData> where TableSectionMutation<RowData> == Value {
		return TableRowMutation(array: sections)
	}
}

extension SignalInterface {
	func arrayMutationToRowMutation<Value>() -> Signal<TableRowMutation<Value>> where ArrayMutation<Value> == OutputValue {
		return map(initialState: 0) { (globalCount: inout Int, arrayMutation: ArrayMutation<Value>) -> TableRowMutation<Value> in
			arrayMutation.delta(&globalCount)
			return TableRowMutation(arrayMutation: arrayMutation, localOffset: 0, globalCount: globalCount)
		}
	}
	
	func arrayMutationToSectionMutation<Value>(header: String? = nil, footer: String? = nil) -> Signal<TableSectionMutation<Value>> where ArrayMutation<Value> == OutputValue {
		return map(initialState: 0) { (globalCount: inout Int, arrayMutation: ArrayMutation<Value>) -> TableSectionMutation<Value> in
			arrayMutation.delta(&globalCount)
			return TableSectionMutation(header: header, footer: footer, rowMutation: TableRowMutation(arrayMutation: arrayMutation, localOffset: 0, globalCount: globalCount))
		}
	}

	func tableData<Value>() -> Signal<TableData<Value>> where ArrayMutation<Value> == OutputValue {
		return Signal.sections(Signal.section(rowSignal: signal.map(initialState: 0) { (globalCount: inout Int, arrayMutation: ArrayMutation<Value>) -> TableRowMutation<Value> in
				arrayMutation.delta(&globalCount)
				return TableRowMutation(arrayMutation: arrayMutation, localOffset: 0, globalCount: globalCount)
			})
		)
	}
	
	static func sections<RowData>(signals: [Signal<TableSectionMutation<RowData>>]) -> Signal<TableRowMutation<TableSectionMutation<RowData>>> where TableRowMutation<TableSectionMutation<RowData>> == OutputValue {
		var result: [Signal<TableRowMutation<TableSectionMutation<RowData>>>] = []
		let count = signals.count
		for (index, sectionSignal) in signals.enumerated() {
			result += sectionSignal.map { section in
				let mutation = ArrayMutation<TableSectionMutation<RowData>>(updatedIndex: index, value: section)
				return TableRowMutation(arrayMutation: mutation, localOffset: 0, globalCount: count, animation: noTableViewAnimation)
			}
		}
		let sections = TableRowMutation<TableSectionMutation<RowData>>(arrayMutation: ArrayMutation(insertedRange: 0..<signals.count, values: Array<TableSectionMutation<RowData>>(repeating: TableSectionMutation<RowData>(), count: signals.count)), localOffset: 0, globalCount: signals.count)
		let (mergedInput, mergedSignal) = Signal<TableRowMutation<TableSectionMutation<RowData>>>.createMergedInput()
		for s in result {
			mergedInput.add(s)
		}
		return mergedSignal.startWith([sections])
	}

	static func sections<RowData>(_ signals: Signal<TableSectionMutation<RowData>>...) -> Signal<TableRowMutation<TableSectionMutation<RowData>>> where TableRowMutation<TableSectionMutation<RowData>> == OutputValue {
		return sections(signals: signals)
	}

	static func section<Value>(header: String? = nil, footer: String? = nil, rowSignal: Signal<TableRowMutation<Value>>) -> Signal<OutputValue> where TableSectionMutation<Value> == OutputValue {
		return rowSignal.map(initialState: false) { (state: inout Bool, value: TableRowMutation<Value>) -> TableSectionMutation<Value> in
			if !state {
				state = true
				return TableSectionMutation<Value>(header: header, footer: footer, rowMutation: value)
			} else {
				return TableSectionMutation<Value>(rowMutation: value)
			}
		}
	}
}

// MARK: ### CwlCoder.swift ###

import Foundation

extension NSCoder {
	func encodeLatest<Interface>(from interface: Interface, forKey: String = .viewStateKey) where Interface: SignalInterface, Interface.OutputValue: Codable {
		if let value = interface.signal.poll() {
			if let data = try? JSONEncoder().encode(value) {
				_ = self.encode(data, forKey: forKey)
			}
		}
	}
	func decodeSend<InputInterface>(to inputInterface: InputInterface, forKey: String = .viewStateKey) where InputInterface: SignalInputInterface, InputInterface.InputValue: Codable {
		if let data = self.decodeObject(forKey: forKey) as? Data, let value = try? JSONDecoder().decode(InputInterface.InputValue.self, from: data) {
			inputInterface.input.send(value: value)
		}
	}
}

extension SignalInterface where OutputValue == Data {
	func decode<Target: Decodable>(as decodableType: Target.Type) -> Signal<Target> {
		return transformValues { v, n in n.send(value: try! JSONDecoder().decode(decodableType, from: v)) }
	}
}

extension SignalInterface where OutputValue: Encodable {
	func pollData() -> Data? {
		return poll().flatMap { try? JSONEncoder().encode($0) }
	}

	func data() -> Signal<Data> {
		return transformValues { v, n in n.send(value: try! JSONEncoder().encode(v)) }
	}

	func logJson(prefix: String = "") -> SignalEndpoint<OutputValue> {
		return subscribe { result in
			switch result {
			case .success(let v):
				if let data = try? JSONEncoder().encode(v), let string = String(data: data, encoding: .utf8) {
					print("\(prefix)\(string)")
				}
			case .failure(let e):
				print("\(prefix)\(e)")
			}
		}
	}
}

extension String {
	static let viewStateKey = "viewStateData"
}

// MARK: ### CwlStateAdapter.swift ###

struct NonPersistentStateAdapterState: Codable, Error {}

protocol StateAdapterBehavior {
	associatedtype State
	associatedtype Message
	associatedtype Notification
	associatedtype PersistentState: Codable = NonPersistentStateAdapterState
	
	static func reducer(state: inout State, message: Message) -> Notification?
	static func resume(state: State) -> Notification?
	static func initialize(message: Message) -> (State?, Notification?)
	static func persistentState(_ state: State) -> PersistentState
	static func stateFromPersistentState(_ state: PersistentState) throws -> State
	static func stateAsStateContainer(_ state: State) -> StateContainer?
	static var stateIsStateContainer: Bool { get }
}

// These extensions are a workaround to the fact that we can't dynamically query conditional conformances yet in Swift 4.1 beta
extension StateAdapterBehavior {
	static var stateIsStateContainer: Bool { return false }
	static func stateAsStateContainer(_ state: State) -> StateContainer? { return nil }
}

// These extensions are a workaround to the fact that we can't dynamically query conditional conformances yet in Swift 4.1 beta
extension StateAdapterBehavior where State: StateContainer {
	static var stateIsStateContainer: Bool { return true }
	static func stateAsStateContainer(_ state: State) -> StateContainer? { return state }
}

extension StateAdapterBehavior where PersistentState == NonPersistentStateAdapterState {
	static func childValues(_ state: State) -> [StateContainer]? {
		return nil
	}
	
	static func persistentState(_ state: State) -> PersistentState {
		return NonPersistentStateAdapterState()
	}
	
	static func stateFromPersistentState(_ state: PersistentState) throws -> State {
		throw NonPersistentStateAdapterState()
	}
}

extension StateAdapterBehavior where PersistentState == State {
	static func persistentState(_ state: State) -> PersistentState {
		return state
	}
	
	static func stateFromPersistentState(_ state: PersistentState) throws -> State {
		return state
	}
}

struct StateAdapter<RB: StateAdapterBehavior>: StateContainer, SignalInputInterface, SignalInterface {
	typealias OutputValue = RB.Notification
	typealias InputValue = RB.Message
	
	private enum Content {
		case none
		case state(RB.State)
		case notification(RB.State?, RB.Notification?)
	}
	
	private let channel: SignalChannel<RB.Message, SignalMultiInput<RB.Message>, Content, SignalMulti<Content>>
	
	var input: SignalInput<RB.Message> { return channel.input }
	var signal: Signal<RB.Notification> { return channel.signal.compactMap {
		switch $0 {
		case .none: return nil
		case .state(let s): return RB.resume(state: s)
		case .notification(_, let n): return n
		}
	} }
	
	private init(initialState: Content) {
		channel = Signal<RB.Message>.multiChannel().reduce(initialState: initialState) { (content: inout Content, message: RB.Message) -> Content in
			switch content {
			case .none, .notification(.none, _):
				let (possibleState, notification) = RB.initialize(message: message)
				if let state = possibleState {
					content = Content.state(state)
				}
				return Content.notification(possibleState, notification)
			case .state(var s):
				let n = RB.reducer(state: &s, message: message)
				content = Content.state(s)
				return Content.notification(s, n)
			case .notification(.some(var s), _):
				let n = RB.reducer(state: &s, message: message)
				content = Content.state(s)
				return Content.notification(s, n)
			}
		}
	}
	
	init(_ initialValue: RB.State) {
		self.init(initialState: Content.state(initialValue))
	}
	
	init() {
		self.init(initialState: Content.none)
	}
	
	func cancel() {
		if RB.stateIsStateContainer, let value = stateSignal.poll(), let sc = RB.stateAsStateContainer(value) {
			sc.cancel()
		}
		input.cancel()
	}
	
	var childValues: [StateContainer] {
		if RB.stateIsStateContainer, let value = stateSignal.poll(), let sc = RB.stateAsStateContainer(value) {
			return sc.childValues
		}
		return []
	}

	var stateSignal: Signal<RB.State> {
		return channel.signal.compactMap { (content: Content) -> RB.State? in
			switch content {
			case .none, .notification(nil, _): return nil
			case .state(let s): return s
			case .notification(.some(let s), _): return s
			}
		}
	}
	
	var persistentValueChanged: Signal<()> {
		if RB.PersistentState.self == NonPersistentStateAdapterState.self {
			return Signal<()>.preclosed()
		}
		
		if !RB.stateIsStateContainer {
			return stateSignal.map { _ in () }.dropActivation()
		}
		
		return channel.signal.flatMapLatest { (content: Content) -> Signal<()> in
			switch content {
			case .state(let s):
				return RB.stateAsStateContainer(s)?.persistentValueChanged ?? Signal<()>.preclosed()
			case .notification(let s as StateContainer, _):
				return s.persistentValueChanged.startWith(())
			default: return Signal<()>.preclosed()
			}
		}.dropActivation()
	}
	
	enum Keys: CodingKey { case `var` }
	
	func encode(to encoder: Encoder) throws {
		if RB.PersistentState.self != NonPersistentStateAdapterState.self, let s = stateSignal.poll() {
			var c = encoder.container(keyedBy: Keys.self)
			try c.encode(RB.persistentState(s), forKey: .var)
		}
	}
	
	init(from decoder: Decoder) throws {
		if RB.PersistentState.self == NonPersistentStateAdapterState.self {
			self.init()
			return
		}
		
		// Decoding must:
		// * Use keyed container
		// * Call `decode`, not `decodeIfPresent`
		// * Catch errors from the `decode` (using try? and optional unwrapping is insufficient)
		// Unless I've missed something, this specific pattern appears to be necessary to correctly decode potentially optional `RB.PersistentState` without *knowing* whether it is defined as an optional – but also handle a situation where it might not be present at all.
		let c = try decoder.container(keyedBy: Keys.self)
		let state = try c.decode(RB.PersistentState.self, forKey: .var)
		try self.init(RB.stateFromPersistentState(state))
	}
}

enum VarChange<Value> {
	case set(Value)
	case update(Value)
	case notify(Value)
}

struct VarBehavior<Value: Codable>: StateAdapterBehavior {
	typealias State = Value
	typealias Message = VarChange<Value>
	typealias Notification = Value
	typealias PersistentState = Value
	
	static func reducer(state: inout State, message: Message) -> Notification? {
		switch message {
		case .set(let v):
			state = v
			return v
		case .update(let v):
			state = v
			return nil
		case .notify(let v):
			return v
		}
	}
	
	static func resume(state: State) -> Notification? {
		return state
	}
	
	static func initialize(message: Message) -> (Value?, Value?) {
		switch message {
		case .set(let v): return (v, v)
		case .update(let v): return (v, nil)
		case .notify(let v): return (nil, v)
		}
	}
}

struct Var<Value: Codable>: StateContainer, SignalInputInterface, SignalInterface {
	typealias OutputValue = Value
	typealias InputValue = Value

	let adapter: StateAdapter<VarBehavior<Value>>
	
	var input: SignalInput<Value> { return Input().map { .set($0) }.bind(to: adapter.input) }
	var signal: Signal<Value> { return adapter.signal }

	init(_ initialValue: Value) {
		adapter = StateAdapter(initialValue)
	}
	var updatingInput: SignalInput<Value> {
		return Input().map { .update($0) }.bind(to: adapter.input)
	}
	
	var notifyingInput: SignalInput<Value> {
		return Input().map { .notify($0) }.bind(to: adapter.input)
	}

	func saveToCoder(_ coder: NSCoder) {
		coder.encodeLatest(from: adapter.stateSignal)
	}
	
	func restoreFromCoder(_ coder: NSCoder) {
		coder.decodeSend(to: input)
	}
	
	var persistentValueChanged: Signal<()> {
		return adapter.persistentValueChanged
	}
	
	func logJson(prefix: String = "") -> SignalEndpoint<Var<Value>> {
		return persistentValueChanged.map { _ in
			self
		}.startWith(self).logJson(prefix: prefix)
	}
	
	var childValues: [StateContainer] {
		return adapter.childValues
	}

	func encode(to encoder: Encoder) throws {
		var c = encoder.singleValueContainer()
		try c.encode(adapter)
	}
	
	init(from decoder: Decoder) throws {
		let c = try decoder.singleValueContainer()
		self.adapter = try c.decode(StateAdapter<VarBehavior<Value>>.self)
	}
}

struct TempBehavior<Value>: StateAdapterBehavior {
	typealias State = Value
	typealias Message = Value
	typealias Notification = Value
	
	static func reducer(state: inout State, message: Message) -> Notification? {
		state = message
		return state
	}
	
	static func resume(state: State) -> Notification? {
		return state
	}
	
	static func initialize(message: Message) -> (Value?, Value?) {
		return (message, message)
	}
}

typealias TempVar<Value> = StateAdapter<TempBehavior<Value>>

struct ToggleBehavior: StateAdapterBehavior {
	typealias State = Bool
	typealias Message = ()
	typealias Notification = Bool
	typealias PersistentState = Bool
	
	static func reducer(state: inout State, message: Message) -> Notification? {
		state = !state
		return state
	}
	
	static func resume(state: State) -> Notification? {
		return state
	}
	
	static func initialize(message: Message) -> (State?, State?) {
		return (false, false)
	}
}

typealias ToggleAdapter = StateAdapter<ToggleBehavior>

// MARK: ### CwlBinderPreparer.swift ###

/// A definition of construct lifecycle events.
protocol BinderPreparer {
	associatedtype Binder: BinderChain

	init()
	
	mutating func prepareBinding(_ binding: Binder.Binding)
	mutating func prepareInstance(_ instance: Binder.Instance, storage: Binder.Storage)
	func applyBinding(_ binding: Binder.Binding, instance: Binder.Instance, storage: Binder.Storage) -> Cancellable?
	mutating func finalizeInstance(_ instance: Binder.Instance, storage: Binder.Storage) -> Cancellable?
}

protocol DerivedPreparer: BinderPreparer where Binder: DerivedBinder {
	var linkedPreparer: Binder.Inherited.Preparer { get set }
}

protocol ConstructingPreparer: DerivedPreparer {
	func constructStorage() -> Binder.Storage
	func constructInstance(subclass: Binder.Instance.Type) -> Binder.Instance
}

extension DerivedPreparer where Binder.Instance: NSObject, Binder.Storage: BinderStorage, Binder.Inherited.Preparer.Binder == Binder.Inherited, Binder.Inherited.Binding.Binder == Binder.Inherited {
	static func construct(bindings: [Binder.Binding], additional: ((Binder.Instance) -> Cancellable?)?, storageConstructor: (Self) -> Binder.Storage, instanceConstructor: (Self) -> Binder.Instance) -> Binder.Instance {
		var preparer = Self.init()
		preparer.prepareBindings(bindings)
		let instance = instanceConstructor(preparer)
		let storage = storageConstructor(preparer)
		if let a = additional {
			preparer.applyBindings(bindings, instance: instance, storage: storage, combine: embedStorageIfInUse(afterAdding: a))
		} else {
			preparer.applyBindings(bindings, instance: instance, storage: storage, combine: embedStorageIfInUse)
		}
		return instance
	}
}

extension DerivedPreparer where Binder.Inherited.Preparer.Binder == Binder.Inherited, Binder.Inherited.Binding.Binder == Binder.Inherited {
	mutating func prepareBindings( _ bindings: [Binder.Binding]) {
		for b in bindings {
			prepareBinding(b)
		}
	}
	
	mutating func applyBindings(_ bindings: [Binder.Binding], instance: Binder.Instance, storage: Binder.Storage, combine: (Binder.Instance, Binder.Storage, [Cancellable]) -> ()) {
		// Prepare.
		prepareInstance(instance, storage: storage)
		
		// Apply styles that need to be applied after construction
		var cancellables = [Cancellable]()
		for b in bindings {
			if let c = applyBinding(b, instance: instance, storage: storage) {
				cancellables.append(c)
			}
		}
		
		// Finalize the instance
		if let c = finalizeInstance(instance, storage: storage) {
			cancellables.append(c)
		}
		
		// Combine the instance and binder
		combine(instance, storage, cancellables)
	}

	mutating func prepareInstance(_ instance: Binder.Instance, storage: Binder.Storage) {
		if let i = instance as? Binder.Inherited.Instance, let s = storage as? Binder.Inherited.Storage {
			linkedPreparer.prepareInstance(i, storage: s)
		}
	}
	
	mutating func finalizeInstance(_ instance: Binder.Instance, storage: Binder.Storage) -> Cancellable? {
		if let i = instance as? Binder.Inherited.Instance, let s = storage as? Binder.Inherited.Storage {
			return linkedPreparer.finalizeInstance(i, storage: s)
		}
		return nil
	}


	func applyBinding(_ binding: Binder.Binding, instance: Binder.Instance, storage: Binder.Storage) -> Cancellable? {
		if let ls = Binder.bindingToInherited(binding), let i = instance as? Binder.Inherited.Instance, let s = storage as? Binder.Inherited.Storage {
			return linkedPreparer.applyBinding(ls, instance: i, storage: s)
		}
		return nil
	}

	mutating func prepareBinding(_ binding: Binder.Binding) {
		if let ls = Binder.bindingToInherited(binding) {
			linkedPreparer.prepareBinding(ls)
		}
	}
}

// MARK: ### CwlDynamicValue.swift ###

struct StaticValue<Value> {
	typealias ValueType = Value
	let value: Value
	init(_ value: Value) {
		self.value = value
	}
	static func fromConstant(_ value: Value) -> StaticValue<Value> {
		return StaticValue<Value>(value)
	}
}

enum DynamicValue<Value> {
	typealias ValueType = Value
	case constant(Value)
	case dynamic(Signal<Value>)
	
	static func fromConstant(_ value: Value) -> DynamicValue<Value> {
		return DynamicValue<Value>.constant(value)
	}
	static func fromDynamic(_ value: Signal<Value>) -> DynamicValue<Value> {
		return DynamicValue<Value>.dynamic(value)
	}

	/// Gets the initial (i.e. used in the constructor) value from the `DynamicValue`
	func capture() -> Captured<Value> {
		switch self {
		case .constant(let v):
			return Captured<Value>(initial: v)
		case .dynamic(let signal):
			let sc = signal.capture()
			return Captured<Value>(initial: sc.activation().0.last, subsequent: sc)
		}
	}
	
	// Gets the subsequent (i.e. after construction) values from the `DynamicValue`
	func apply<I: AnyObject, B: BinderStorage>(_ instance: I, _ storage: B, _ onError: Value? = nil, handler: @escaping (I, B, Value) -> Void) -> Cancellable? {
		switch self {
		case .constant(let v):
			handler(instance, storage, v)
			return nil
		case .dynamic(let signal):
			return signal.subscribe(context: .main) { [weak instance, weak storage] r in
				guard let i = instance, let s = storage else { return }
				switch (r, onError) {
				case (.success(let v), _): handler(i, s, v)
				case (.failure, .some(let v)): handler(i, s, v)
				case (.failure, .none): break
				}
			}
		}
	}
}

struct Captured<Value> {
	private var capturedValue: Value?
	var shouldResend: Bool
	let subsequent: SignalCapture<Value>?
	
	init(initial: Value? = nil, shouldResend: Bool = true, subsequent: SignalCapture<Value>? = nil) {
		self.capturedValue = initial
		self.shouldResend = shouldResend
		self.subsequent = subsequent
	}
	
	mutating func initial() -> Value? {
		let c = capturedValue
		capturedValue = nil
		shouldResend = false
		return c
	}

	func resume() -> Signal<Value>? {
		if let s = subsequent {
			return s.resume(resend: shouldResend)
		} else if shouldResend, let i = capturedValue {
			return Signal<Value>.preclosed(i)
		}
		return nil
	}
}

extension Signal {
	func apply<I: AnyObject, B: BinderStorage>(_ instance: I?, _ storage: B?, handler: @escaping (I, B, OutputValue) -> Void) -> Cancellable? {
		return subscribeValues(context: .main) { [weak instance, weak storage] v in
			guard let i = instance, let s = storage else { return }
			handler(i, s, v)
		}
	}
}

extension SignalCapture {
	func apply<I: AnyObject, B: BinderStorage>(_ instance: I, _ storage: B, handler: @escaping (I, B, OutputValue) -> Void) -> Cancellable? {
		return subscribeValues(context: .main) { [weak instance, weak storage] v in
			guard let i = instance, let s = storage else { return }
			handler(i, s, v)
		}
	}
}

extension SignalInterface {
	func adhocBinding<Subclass: AnyObject>(toType: Subclass.Type, using: @escaping (Subclass, OutputValue) -> Void) -> (AnyObject) -> Cancellable? {
		return { (instance: AnyObject) -> Cancellable? in
			return self.signal.subscribeValues(context: .main) { [weak instance] value in
				if let i = instance as? Subclass {
					using(i, value)
				}
			}
		}
	}
}

// MARK: ### CwlStackAdapter.swift ###

import Foundation

/// An "Either" type for use in scenarios where "Equatable" and "Codable" are required but there's only ever a single "Master" instance so equality is implied. This is common in Navigation Controller stacks and Split Views.
enum MasterOrDetail<Master: StateContainer, Detail: StateContainer>: StateContainer {
	case master(Master)
	case detail(Detail)
	
	var childValues: [StateContainer] {
		switch self {
		case .master(let tvm): return [tvm]
		case .detail(let dvm): return [dvm]
		}
	}

	enum Keys: CodingKey { case master, detail }
	
	func encode(to encoder: Encoder) throws {
		var c = encoder.container(keyedBy: Keys.self)
		switch self {
		case .master(let tvm): try c.encode(tvm, forKey: .master)
		case .detail(let dvm): try c.encode(dvm, forKey: .detail)
		}
	}
	
	init(from decoder: Decoder) throws {
		let c = try decoder.container(keyedBy: Keys.self)
		if let tvm = try c.decodeIfPresent(Master.self, forKey: .master) {
			self = .master(tvm)
		} else {
			self = .detail(try c.decode(Detail.self, forKey: .detail))
		}
	}
}

/// This "StateAdapter" is a `ModelSignalValue` that manages a stack of navigation items as might be used by a UINavigationController. The adapter converts `push`, `popToCount` and `reload` messages into updates to the array of `PathElement`. The adapter includes convenient input signals, animated output signals and includes automatic implementation of coding and notification protocols.
struct StackAdapterBehavior<PathElement: Codable>: StateAdapterBehavior {
	typealias State = [PathElement]
	typealias Message = StackMutation<PathElement>
	typealias Notification = StackMutation<PathElement>
	typealias PersistentState = State
	
	static func reducer(state: inout State, message: Message) -> Notification? {
		switch message {
		case .push(let e):
			state.append(e)
			return message
		case .pop:
			_ = state.popLast()
			return message
		case .popToCount(let i):
			if i >= 1, i < state.count {
				state.removeLast(state.count - i)
				return message
			}
			return nil
		case .reload(let newStack):
			state = newStack
			return message
		}
	}
	
	static func resume(state: State) -> Notification? {
		return .reload(state)
	}
	
	static func initialize(message: Message) -> (State?, Notification?) {
		var state = [PathElement]()
		let n = reducer(state: &state, message: message)
		return (state, n)
	}
}

extension StateAdapter where RB.State: Collection, RB.Message == StackMutation<RB.State.Element> {
	var pushInput: SignalInput<RB.State.Element> {
		return Signal<RB.State.Element>.channel().map { RB.Message.push($0) }.bind(to: input)
	}

	var poppedToCount: SignalInput<Int> {
		return Signal<Int>.channel().map { RB.Message.popToCount($0) }.bind(to: input)
	}
}

typealias StackAdapter<PathElement: Codable> = StateAdapter<StackAdapterBehavior<PathElement>>

// MARK: ### CwlLayout.swift ###

#if os(macOS)
	import AppKit
#else
	import UIKit
#endif

protocol ViewInstance {
	var viewInstance: Layout.View { get }
}
extension Layout.View: ViewInstance {
	var viewInstance: Layout.View {
		return self
	}
}

/// When a layout is applied, it can animate one of three ways:
///
/// - none: do not animate to the new layout
/// - all: animate to the new layout
/// - subsequent: animate to the new layout only if there was a previous layout
enum AnimationChoice {
	case none
	case all
	case subsequent
}


// This type handles a combination of `layoutMargin` and `safeAreaMargin` inset edges. If a `safeArea` edge is specified, it will be used instead of `layout` edge.
struct MarginEdges: OptionSet {
	static var none: MarginEdges { return MarginEdges(rawValue: 0) }
	static var topLayout: MarginEdges { return MarginEdges(rawValue: 1) }
	static var leadingLayout: MarginEdges { return MarginEdges(rawValue: 2) }
	static var bottomLayout: MarginEdges { return MarginEdges(rawValue: 4) }
	static var trailingLayout: MarginEdges { return MarginEdges(rawValue: 8) }
	static var topSafeArea: MarginEdges { return MarginEdges(rawValue: 16) }
	static var leadingSafeArea: MarginEdges { return MarginEdges(rawValue: 32) }
	static var bottomSafeArea: MarginEdges { return MarginEdges(rawValue: 64) }
	static var trailingSafeArea: MarginEdges { return MarginEdges(rawValue: 128) }
	static var allLayout: MarginEdges { return [.topLayout, .leadingLayout, .bottomLayout, .trailingLayout] }
	static var allSafeArea: MarginEdges { return [.topSafeArea, .leadingSafeArea, .bottomSafeArea, .trailingSafeArea] }
	let rawValue: UInt
	init(rawValue: UInt) {
		self.rawValue = rawValue
	}
}

#if os(macOS)
	extension NSView {
		/// Adds the views contained by `layout` in the arrangment described by the layout to `self`.
		///
		/// - Parameter layout: a set of views and layout descriptions
		func applyLayout(_ layout: Layout?) {
			applyLayoutToView(view: self, params: layout.map { (layout: $0, bounds: Layout.Bounds(view: self, marginEdges: .none)) })
		}
	}
#else
	extension UIView {
		/// Adds the views contained by `layout` in the arrangment described by the layout to `self`.
		///
		/// - Parameter layout: a set of views and layout descriptions
		func applyLayout(_ layout: Layout?) {
			applyLayoutToView(view: self, params: layout.map { (layout: $0, bounds: Layout.Bounds(view: self, marginEdges: $0.marginEdges)) })
		}
	}
	
	extension UIScrollView {
		/// Adds the views contained by `layout` in the arrangment described by the layout to `self`.
		///
		/// - Parameter layout: a set of views and layout descriptions
		@available(iOS 11, *)
		func applyContentLayout(_ layout: Layout?) {
			applyLayoutToView(view: self, params: layout.map { (layout: $0, bounds: Layout.Bounds(scrollView: self)) })
		}
	}
	
	extension UIViewController {
		/// Adds the views contained by `layout` in the arrangment described by the layout to `self`.
		///
		/// NOTE: prior to iOS 11, this is required to handle the UIViewController topLayoutGuide and bottomLayoutGuide.
		///
		/// - Parameter layout: a set of views and layout descriptions
		@available(iOS, introduced: 7.0, deprecated: 11.0, message: "This function exists to layout relative to view controller layout guides prior to iOS 11. On iOS 11 and later, use safe area margins and apply the layout directly to the view")
		func applyLayout(_ layout: Layout?) {
			if let l = layout, l.marginEdges.contains(.topSafeArea) || l.marginEdges.contains(.bottomSafeArea) {
				let wrapper = Layout(
					axis: .vertical,
					align: .fill,
					entities: [Layout.Entity(.layout(l, size: nil))]
				)
				applyLayoutToView(view: self.view, params: (layout: wrapper, bounds: Layout.Bounds(viewController: self, marginEdges: l.marginEdges)))
			} else {
				applyLayoutToView(view: self.view, params: layout.map { (layout: $0, bounds: Layout.Bounds(viewController: self, marginEdges: $0.marginEdges)) })
			}
		}
	}
#endif

/// A data structure for describing a layout as a series of nested columns and rows.
struct Layout {
	/// A rough equivalent to UIStackViewAlignment, minus baseline cases which aren't handled
	enum Alignment { case leading, trailing, center, fill }
	
	#if os(macOS)
		typealias Axis = NSUserInterfaceLayoutOrientation
		typealias View = NSView
		typealias Guide = NSLayoutGuide
	#else
		typealias Axis = UILayoutConstraintAxis
		typealias View = UIView
		typealias Guide = UILayoutGuide
	#endif
	
	/// Layout is either horizontal or vertical (although any element within the layout may be a layout in the perpendicular direction)
	let axis: Axis
	
	/// Within the horizontal row or vertical column, layout entities may fill, center or align-leading or align-trailing
	let align: Alignment
	
	/// The layout may extend to the view bounds or may be limited by the safeAreaMargins or layoutMargins. The safeArea insets supercede the layoutMargins (prior to iOS 11, safeArea is interpreted as UIViewController top/bottom layout guides when laying out within a UIViewController, otherwise it is treated as a synonym for the layoutMargins). This value has no effect on macOS.	
	let marginEdges: MarginEdges
	
	/// When applied to the top level `Layout` passed to 'applyLayout`, then replacing an existing layout on a view, if this variable is true, after applying the new layout, `layoutIfNeeded` will be called inside a `UIView.beginAnimations`/`UIView.endAnimations` block. Has no effect when set on a child `Layout`.
	let animate: AnimationChoice
	
	/// This is the list of views, spaces and sublayouts that will be layed out.
	var entities: [Entity]
	
	/// The default constructor assigns all values. In general, it's easier to use the `.horizontal` or `.vertical` constructor where possible.
	init(axis: Axis, align: Alignment = .fill, marginEdges: MarginEdges = .allSafeArea, animate: AnimationChoice = .subsequent, entities: [Entity]) {
		self.axis = axis
		self.align = align
		self.entities = entities
		self.marginEdges = marginEdges
		self.animate = animate
	}
	
	/// A convenience constructor for a horizontal layout
	static func horizontal(align: Alignment = .fill, marginEdges: MarginEdges = .allSafeArea, animate: AnimationChoice = .subsequent, _ entities: Entity...) -> Layout {
		return Layout(axis: .horizontal, align: align, marginEdges: marginEdges, animate: animate, entities: entities)
	}
	
	/// A convenience constructor for a vertical layout
	static func vertical(align: Alignment = .fill, marginEdges: MarginEdges = .allSafeArea, animate: AnimationChoice = .subsequent, _ entities: Entity...) -> Layout {
		return Layout(axis: .vertical, align: align, marginEdges: marginEdges, animate: animate, entities: entities)
	}
	
	// Used for removing all views from their superviews
	fileprivate func forEachView(_ visit: (View) -> ()) {
		entities.forEach { $0.forEachView(visit) }
	}

	/// The `Layout` describes a series of these `Entity`s which may be a space, a view or a sublayout. There is also a special `matched` layout which allows a series of "same length" entities.
	///
	/// - interViewSpace: AppKit and UIKit use an 8 screen unit space as the "standard" space between adjacent views.
	/// - space: an arbitrary space between views
	/// - view: a view with optional width and height (if not specified, the view will use its "intrinsic" size or will fill the available layout space)
	/// - layout: a nested layout which may be parallel or perpedicular to its container and whose size may be specified (like view)
	/// - matched: a sequence of alternating "same size" and independent entities (you can use `.space(0)` if you don't want independent entities).
	struct Entity {
		enum Content {
			case space(Dimension)
			case sizedView(Layout.View, Size?)
			indirect case layout(Layout, size: Size?)
			indirect case matched(Entity, [(independent: Entity, same: Entity)], priority: Dimension.Priority)
		}
		let content: Content
		init(_ content: Content) {
			self.content = content
		}
		
		fileprivate func forEachView(_ visit: (Layout.View) -> ()) {
			switch content {
			case .sizedView(let v, _): visit(v.viewInstance)
			case .layout(let l, _): l.forEachView(visit)
			case .matched(let entity, let pairArray, _):
				entity.forEachView(visit)
				pairArray.forEach {
					$0.same.forEachView(visit)
					$0.independent.forEachView(visit)
				}
			default: break
			}
		}
		
		static func space(_ dimension: Dimension = .standardSpace) -> Entity {
			return Entity(.space(dimension))
		}
		
		static func view(length: Dimension? = nil, breadth: Dimension? = nil, relative: Bool = false, _ view: ViewInstance) -> Entity {
			let size = Size(length: length, breadth: breadth, relative: relative)
			return Entity(.sizedView(view.viewInstance, size))
		}
		
		static func horizontal(align: Alignment = .fill, length: Dimension? = nil, breadth: Dimension? = nil, relative: Bool = false, _ entities: Entity...) -> Entity {
			let size = Size(length: length, breadth: breadth, relative: relative)
			return Entity(.layout(Layout(axis: .horizontal, align: align, marginEdges: .none, entities: entities), size: size))
		}
		
		static func vertical(align: Alignment = .fill, length: Dimension? = nil, breadth: Dimension? = nil, relative: Bool = false, _ entities: Entity...) -> Entity {
			let size = Size(length: length, breadth: breadth, relative: relative)
			return Entity(.layout(Layout(axis: .vertical, align: align, marginEdges: .none, entities: entities), size: size))
		}
		
		static func matchedPair(_ left: Entity, _ right: Entity, separator: Entity = .space(), priority: Dimension.Priority = .required) -> Entity {
			return Entity(.matched(left, [(independent: separator, same: right)], priority: priority))
		}
		
		static func matched(_ first: Entity, _ subsequent: [(independent: Entity, same: Entity)], priority: Dimension.Priority = .required) -> Entity {
			return Entity(.matched(first, subsequent, priority: priority))
		}
	}

	/// A `Size` is the combination of both length (size of a layout object in the direction of layout) or breadth (size of a layout object perpendicular to the layout direction). If the length includes a ratio, it is relative to the parent container but the breadth can be relative to the length, allowing for specifying an aspect ratio.
	struct Size {
		let length: Dimension?
		let breadth: Dimension?
		let relative: Bool
		
		init(length: Dimension? = nil, breadth: Dimension?, relative: Bool = false) {
			self.length = length
			self.breadth = breadth
			self.relative = relative
		}
	}

	/// When length (size of a layout object in the direction of layout) or breadth (size of a layout object perpendicular to the layout direction) is specified, it can be specified:
	///	* relative to the parent container (ratio)
	///	* in raw screen units (constant)
	/// The greater/less than and priority can also be specified.
	struct Dimension: ExpressibleByFloatLiteral, ExpressibleByIntegerLiteral {
		typealias FloatLiteralType = Double
		typealias IntegerLiteralType = Int
		
		#if os(macOS)
			typealias Relation = NSLayoutConstraint.Relation
			typealias Priority = NSLayoutConstraint.Priority
		#else
			typealias Relation = NSLayoutRelation
			typealias Priority = UILayoutPriority
		#endif
		
		let ratio: CGFloat
		let constant: CGFloat
		let relationship: Relation
		let priority: Dimension.Priority
		init(ratio: CGFloat = 0, constant: CGFloat = 0, relationship: Dimension.Relation = .equal, priority: Dimension.Priority = .required) {
			self.ratio = ratio
			self.constant = constant
			self.relationship = relationship
			self.priority = priority
		}
		
		init(floatLiteral value: Double) {
			self.init(constant: CGFloat(value))
		}
		
		init(integerLiteral value: Int) {
			self.init(constant: CGFloat(value))
		}
		
		static var standardSpace: Dimension = 8
		
		static func lessThanOrEqualTo(ratio: CGFloat = 0, constant: CGFloat = 0, priority: Dimension.Priority = .required) -> Dimension {
			return Dimension(ratio: ratio, constant: constant, relationship: .lessThanOrEqual, priority: priority)
		}
		
		static func greaterThanOrEqualTo(ratio: CGFloat = 0, constant: CGFloat = 0, priority: Dimension.Priority = .required) -> Dimension {
			return Dimension(ratio: ratio, constant: constant, relationship: .greaterThanOrEqual, priority: priority)
		}
		
		static func equalTo(ratio: CGFloat = 0, constant: CGFloat = 0, priority: Dimension.Priority = .required) -> Dimension {
			return Dimension(ratio: ratio, constant: constant, relationship: .equal, priority: priority)
		}
		
		static var fillRemaining: Dimension {
			return greaterThanOrEqualTo(constant: 0, priority: .userHigh)
		}
	}

	/// Bounds are used internally to capture a set of guides and anchors. On the Mac, these are merely copied from a single NSLayoutGuide or an NSView. On iOS, these may be copied from a blend of UIViewController top/bottomLayoutGuides, safeAreaLayoutGuides, layoutMarginsGuides or a UIView.
	fileprivate struct Bounds {
		var leading: NSLayoutXAxisAnchor
		var top: NSLayoutYAxisAnchor
		var trailing: NSLayoutXAxisAnchor
		var bottom: NSLayoutYAxisAnchor
		var width: NSLayoutDimension
		var height: NSLayoutDimension
		var centerX: NSLayoutXAxisAnchor
		var centerY: NSLayoutYAxisAnchor
		
		fileprivate init(box: Layout.Box) {
			leading = box.leadingAnchor
			top = box.topAnchor
			trailing = box.trailingAnchor
			bottom = box.bottomAnchor
			width = box.widthAnchor
			height = box.heightAnchor
			centerX = box.centerXAnchor
			centerY = box.centerYAnchor
		}
		
		#if os(iOS)
			@available(iOS 11, *)
			fileprivate init(scrollView: UIScrollView) {
				leading = scrollView.contentLayoutGuide.leadingAnchor
				top = scrollView.contentLayoutGuide.topAnchor
				trailing = scrollView.contentLayoutGuide.trailingAnchor
				bottom = scrollView.contentLayoutGuide.bottomAnchor
				width = scrollView.contentLayoutGuide.widthAnchor
				height = scrollView.contentLayoutGuide.heightAnchor
				centerX = scrollView.contentLayoutGuide.centerXAnchor
				centerY = scrollView.contentLayoutGuide.centerYAnchor
			}
			
			@available(iOS, introduced: 7.0, deprecated: 11.0)
			fileprivate init(viewController: UIViewController, marginEdges: MarginEdges) {
				let view = viewController.view!
				leading = marginEdges.contains(.leadingSafeArea) || marginEdges.contains(.leadingLayout) ? view.layoutMarginsGuide.leadingAnchor : view.leadingAnchor
				top = marginEdges.contains(.topSafeArea) ? viewController.topLayoutGuide.bottomAnchor : (marginEdges.contains(.topLayout) ? view.layoutMarginsGuide.topAnchor : view.topAnchor)
				trailing = marginEdges.contains(.trailingSafeArea) || marginEdges.contains(.trailingLayout) ? view.layoutMarginsGuide.trailingAnchor : view.trailingAnchor
				bottom = marginEdges.contains(.bottomSafeArea) ? viewController.bottomLayoutGuide.topAnchor : (marginEdges.contains(.bottomLayout) ? view.layoutMarginsGuide.bottomAnchor : view.bottomAnchor)
				width = (marginEdges.contains(.leadingSafeArea) || marginEdges.contains(.leadingLayout)) && (marginEdges.contains(.trailingSafeArea) || marginEdges.contains(.trailingLayout)) ? view.layoutMarginsGuide.widthAnchor : view.widthAnchor
				height = (marginEdges.contains(.topSafeArea) || marginEdges.contains(.topLayout)) && (marginEdges.contains(.bottomSafeArea) || marginEdges.contains(.bottomLayout)) ? view.layoutMarginsGuide.heightAnchor : view.heightAnchor
				centerX = (marginEdges.contains(.leadingSafeArea) || marginEdges.contains(.leadingLayout)) && (marginEdges.contains(.trailingSafeArea) || marginEdges.contains(.trailingLayout)) ? view.layoutMarginsGuide.centerXAnchor : view.centerXAnchor
				centerY = (marginEdges.contains(.topSafeArea) || marginEdges.contains(.topLayout)) && (marginEdges.contains(.bottomSafeArea) || marginEdges.contains(.bottomLayout)) ? view.layoutMarginsGuide.centerYAnchor : view.centerYAnchor
			}
			
			fileprivate init(view: Layout.View, marginEdges: MarginEdges) {
				if #available(iOS 11.0, *) {
					#if swift(>=4)
						leading = marginEdges.contains(.leadingSafeArea) ? view.safeAreaLayoutGuide.leadingAnchor : (marginEdges.contains(.leadingLayout) ? view.layoutMarginsGuide.leadingAnchor : view.leadingAnchor)
						top = marginEdges.contains(.topSafeArea) ? view.safeAreaLayoutGuide.topAnchor : (marginEdges.contains(.topLayout) ? view.layoutMarginsGuide.topAnchor : view.topAnchor)
						trailing = marginEdges.contains(.trailingSafeArea) ? view.safeAreaLayoutGuide.trailingAnchor : (marginEdges.contains(.trailingLayout) ? view.layoutMarginsGuide.trailingAnchor : view.trailingAnchor)
						bottom = marginEdges.contains(.bottomSafeArea) ? view.safeAreaLayoutGuide.bottomAnchor : (marginEdges.contains(.bottomLayout) ? view.layoutMarginsGuide.bottomAnchor : view.bottomAnchor)
						width = (marginEdges.contains(.leadingSafeArea) && marginEdges.contains(.trailingSafeArea)) ? view.safeAreaLayoutGuide.widthAnchor : (marginEdges.contains(.leadingLayout) && marginEdges.contains(.trailingLayout) ? view.layoutMarginsGuide.widthAnchor : view.widthAnchor)
						height = (marginEdges.contains(.leadingSafeArea) && marginEdges.contains(.trailingSafeArea)) ? view.safeAreaLayoutGuide.heightAnchor : (marginEdges.contains(.leadingLayout) && marginEdges.contains(.trailingLayout) ? view.layoutMarginsGuide.heightAnchor : view.heightAnchor)
						centerX = (marginEdges.contains(.leadingSafeArea) && marginEdges.contains(.trailingSafeArea)) ? view.safeAreaLayoutGuide.centerXAnchor : (marginEdges.contains(.leadingLayout) && marginEdges.contains(.trailingLayout) ? view.layoutMarginsGuide.centerXAnchor : view.centerXAnchor)
						centerY = (marginEdges.contains(.leadingSafeArea) && marginEdges.contains(.trailingSafeArea)) ? view.safeAreaLayoutGuide.centerYAnchor : (marginEdges.contains(.leadingLayout) && marginEdges.contains(.trailingLayout) ? view.layoutMarginsGuide.centerYAnchor : view.centerYAnchor)
					#else
						leading = marginEdges.contains(.leadingSafeArea) || marginEdges.contains(.leadingLayout) ? view.layoutMarginsGuide.leadingAnchor : view.leadingAnchor
						top = marginEdges.contains(.topSafeArea) || marginEdges.contains(.topLayout) ? view.layoutMarginsGuide.topAnchor : view.topAnchor
						trailing = marginEdges.contains(.trailingSafeArea) || marginEdges.contains(.trailingLayout) ? view.layoutMarginsGuide.trailingAnchor : view.trailingAnchor
						bottom = marginEdges.contains(.bottomSafeArea) || marginEdges.contains(.bottomLayout) ? view.layoutMarginsGuide.bottomAnchor : view.bottomAnchor
						width = (marginEdges.contains(.leadingSafeArea) || marginEdges.contains(.leadingLayout)) && (marginEdges.contains(.trailingSafeArea) || marginEdges.contains(.trailingLayout)) ? view.layoutMarginsGuide.widthAnchor : view.widthAnchor
						height = (marginEdges.contains(.topSafeArea) || marginEdges.contains(.topLayout)) && (marginEdges.contains(.bottomSafeArea) || marginEdges.contains(.bottomLayout)) ? view.layoutMarginsGuide.heightAnchor : view.heightAnchor
						centerX = (marginEdges.contains(.leadingSafeArea) || marginEdges.contains(.leadingLayout)) && (marginEdges.contains(.trailingSafeArea) || marginEdges.contains(.trailingLayout)) ? view.layoutMarginsGuide.centerXAnchor : view.centerXAnchor
						centerY = (marginEdges.contains(.topSafeArea) || marginEdges.contains(.topLayout)) && (marginEdges.contains(.bottomSafeArea) || marginEdges.contains(.bottomLayout)) ? view.layoutMarginsGuide.centerYAnchor : view.centerYAnchor
					#endif
				} else {
					leading = marginEdges.contains(.leadingSafeArea) || marginEdges.contains(.leadingLayout) ? view.layoutMarginsGuide.leadingAnchor : view.leadingAnchor
					top = marginEdges.contains(.topSafeArea) || marginEdges.contains(.topLayout) ? view.layoutMarginsGuide.topAnchor : view.topAnchor
					trailing = marginEdges.contains(.trailingSafeArea) || marginEdges.contains(.trailingLayout) ? view.layoutMarginsGuide.trailingAnchor : view.trailingAnchor
					bottom = marginEdges.contains(.bottomSafeArea) || marginEdges.contains(.bottomLayout) ? view.layoutMarginsGuide.bottomAnchor : view.bottomAnchor
					width = (marginEdges.contains(.leadingSafeArea) || marginEdges.contains(.leadingLayout)) && (marginEdges.contains(.trailingSafeArea) || marginEdges.contains(.trailingLayout)) ? view.layoutMarginsGuide.widthAnchor : view.widthAnchor
					height = (marginEdges.contains(.topSafeArea) || marginEdges.contains(.topLayout)) && (marginEdges.contains(.bottomSafeArea) || marginEdges.contains(.bottomLayout)) ? view.layoutMarginsGuide.heightAnchor : view.heightAnchor
					centerX = (marginEdges.contains(.leadingSafeArea) || marginEdges.contains(.leadingLayout)) && (marginEdges.contains(.trailingSafeArea) || marginEdges.contains(.trailingLayout)) ? view.layoutMarginsGuide.centerXAnchor : view.centerXAnchor
					centerY = (marginEdges.contains(.topSafeArea) || marginEdges.contains(.topLayout)) && (marginEdges.contains(.bottomSafeArea) || marginEdges.contains(.bottomLayout)) ? view.layoutMarginsGuide.centerYAnchor : view.centerYAnchor
				}
			}
		#else
			fileprivate init(view: Layout.View, marginEdges: MarginEdges) {
				leading = view.leadingAnchor
				top = view.topAnchor
				trailing = view.trailingAnchor
				bottom = view.bottomAnchor
				width = view.widthAnchor
				height = view.heightAnchor
				centerX = view.centerXAnchor
				centerY = view.centerYAnchor
			}
		#endif
	}

	fileprivate struct State {
		let view: View
		let storage: Storage
		
		var dimension: Dimension? = nil
		var previousEntityBounds: Bounds? = nil
		var containerBounds: Bounds
		
		init(containerBounds: Bounds, in view: View, storage: Storage) {
			self.containerBounds = containerBounds
			self.view = view
			self.storage = storage
		}
	}

	fileprivate class Storage: NSObject {
		let layout: Layout
		var constraints: [NSLayoutConstraint] = []
		var boxes: [Layout.Box] = []
		
		init(layout: Layout) {
			self.layout = layout
		}
	}

	#if true && DEBUG
		fileprivate typealias Box = Layout.View
	#else
		fileprivate typealias Box = Layout.Guide
	#endif
	
	fileprivate func constrain(bounds: Bounds, leading: Dimension, length: Dimension?, breadth: Dimension?, relative: Bool, state: inout State) {
		if axis == .horizontal {
			let leadingAnchor = bounds.leading
			let preceedingAnchor = state.containerBounds.leading
			let leadingConstraint: NSLayoutConstraint
			switch leading.relationship {
			case .equal: leadingConstraint = leadingAnchor.constraint(equalTo: preceedingAnchor, constant: leading.constant)
			case .lessThanOrEqual: leadingConstraint = leadingAnchor.constraint(lessThanOrEqualTo: preceedingAnchor, constant: leading.constant)
			case .greaterThanOrEqual: leadingConstraint = leadingAnchor.constraint(greaterThanOrEqualTo: preceedingAnchor, constant: leading.constant)
			}
			leadingConstraint.priority = leading.priority
			state.storage.constraints.append(leadingConstraint)
			leadingConstraint.isActive = true
			
			if let l = length {
				let widthAnchor = bounds.width
				let widthConstraint: NSLayoutConstraint
				switch l.relationship {
				case .equal: widthConstraint = widthAnchor.constraint(equalTo: state.containerBounds.width, multiplier: l.ratio, constant: l.constant)
				case .lessThanOrEqual: widthConstraint = widthAnchor.constraint(lessThanOrEqualTo: state.containerBounds.width, multiplier: l.ratio, constant: l.constant)
				case .greaterThanOrEqual: widthConstraint = widthAnchor.constraint(greaterThanOrEqualTo: state.containerBounds.width, multiplier: l.ratio, constant: l.constant)
				}
				widthConstraint.priority = l.priority
				state.storage.constraints.append(widthConstraint)
				widthConstraint.isActive = true
			}
			
			if let b = breadth {
				let heightAnchor = bounds.height
				let secondAnchor = relative ? bounds.width : state.containerBounds.height
				let heightConstraint: NSLayoutConstraint
				switch b.relationship {
				case .equal: heightConstraint = heightAnchor.constraint(equalTo: secondAnchor, multiplier: b.ratio, constant: b.constant)
				case .lessThanOrEqual: heightConstraint = heightAnchor.constraint(lessThanOrEqualTo: secondAnchor, multiplier: b.ratio, constant: b.constant)
				case .greaterThanOrEqual: heightConstraint = heightAnchor.constraint(greaterThanOrEqualTo: secondAnchor, multiplier: b.ratio, constant: b.constant)
				}
				heightConstraint.priority = b.priority
				state.storage.constraints.append(heightConstraint)
				heightConstraint.isActive = true
			}
			
			switch self.align {
			case .leading:
				let top = bounds.top.constraint(equalTo: state.containerBounds.top)
				let bottom = bounds.bottom.constraint(equalTo: state.containerBounds.bottom)
				let bottom2 = bounds.bottom.constraint(lessThanOrEqualTo: state.containerBounds.bottom)
				top.priority = .required
				bottom.priority = .userLow
				bottom2.priority = .userHigh
				top.isActive = true
				bottom.isActive = true
				bottom2.isActive = true
				state.storage.constraints.append(top)
				state.storage.constraints.append(bottom)
				state.storage.constraints.append(bottom2)
			case .trailing:
				let top = bounds.top.constraint(equalTo: state.containerBounds.top)
				let top2 = bounds.top.constraint(greaterThanOrEqualTo: state.containerBounds.top)
				let bottom = bounds.bottom.constraint(equalTo: state.containerBounds.bottom)
				top.priority = .userLow
				top2.priority = .userHigh
				bottom.priority = .required
				top.isActive = true
				top2.isActive = true
				bottom.isActive = true
				state.storage.constraints.append(top)
				state.storage.constraints.append(top2)
				state.storage.constraints.append(bottom)
			case .center:
				let center = bounds.centerY.constraint(equalTo: state.containerBounds.centerY)
				center.priority = .required
				center.isActive = true
				state.storage.constraints.append(center)
				let height = bounds.height.constraint(equalTo: state.containerBounds.height)
				height.priority = .userLow
				height.isActive = true
				state.storage.constraints.append(height)
			case .fill:
				let top = bounds.top.constraint(equalTo: state.containerBounds.top)
				let bottom = bounds.bottom.constraint(equalTo: state.containerBounds.bottom)
				top.priority = .userHigh
				bottom.priority = .userHigh
				top.isActive = true
				bottom.isActive = true
				state.storage.constraints.append(top)
				state.storage.constraints.append(bottom)
			}
			
			state.containerBounds.leading = bounds.trailing
		} else {
			let leadingAnchor = bounds.top
			let preceedingAnchor = state.containerBounds.top
			let leadingConstraint: NSLayoutConstraint
			switch leading.relationship {
			case .equal: leadingConstraint = leadingAnchor.constraint(equalTo: preceedingAnchor, constant: leading.constant)
			case .lessThanOrEqual: leadingConstraint = leadingAnchor.constraint(lessThanOrEqualTo: preceedingAnchor, constant: leading.constant)
			case .greaterThanOrEqual: leadingConstraint = leadingAnchor.constraint(greaterThanOrEqualTo: preceedingAnchor, constant: leading.constant)
			}
			leadingConstraint.priority = leading.priority
			state.storage.constraints.append(leadingConstraint)
			leadingConstraint.isActive = true
			
			if let l = length {
				let heightAnchor = bounds.height
				let heightConstraint: NSLayoutConstraint
				switch l.relationship {
				case .equal: heightConstraint = heightAnchor.constraint(equalTo: state.containerBounds.height, multiplier: l.ratio, constant: l.constant)
				case .lessThanOrEqual: heightConstraint = heightAnchor.constraint(lessThanOrEqualTo: state.containerBounds.height, multiplier: l.ratio, constant: l.constant)
				case .greaterThanOrEqual: heightConstraint = heightAnchor.constraint(greaterThanOrEqualTo: state.containerBounds.height, multiplier: l.ratio, constant: l.constant)
				}
				heightConstraint.priority = l.priority
				state.storage.constraints.append(heightConstraint)
				heightConstraint.isActive = true
			}
			
			if let b = breadth {
				let widthAnchor = bounds.width
				let secondAnchor = relative ? bounds.height : state.containerBounds.width
				let widthConstraint: NSLayoutConstraint
				switch b.relationship {
				case .equal: widthConstraint = widthAnchor.constraint(equalTo: secondAnchor, multiplier: b.ratio, constant: b.constant)
				case .lessThanOrEqual: widthConstraint = widthAnchor.constraint(lessThanOrEqualTo: secondAnchor, multiplier: b.ratio, constant: b.constant)
				case .greaterThanOrEqual: widthConstraint = widthAnchor.constraint(greaterThanOrEqualTo: secondAnchor, multiplier: b.ratio, constant: b.constant)
				}
				widthConstraint.priority = b.priority
				state.storage.constraints.append(widthConstraint)
				widthConstraint.isActive = true
			}
			
			switch self.align {
			case .leading:
				let leading = bounds.leading.constraint(equalTo: state.containerBounds.leading)
				let trailing = bounds.trailing.constraint(equalTo: state.containerBounds.trailing)
				let trailing2 = bounds.trailing.constraint(lessThanOrEqualTo: state.containerBounds.trailing)
				leading.priority = .required
				trailing.priority = .userLow
				trailing2.priority = .userHigh
				leading.isActive = true
				trailing.isActive = true
				trailing2.isActive = true
				state.storage.constraints.append(leading)
				state.storage.constraints.append(trailing)
				state.storage.constraints.append(trailing2)
			case .trailing:
				let leading = bounds.leading.constraint(equalTo: state.containerBounds.leading)
				let leading2 = bounds.leading.constraint(greaterThanOrEqualTo: state.containerBounds.leading)
				let trailing = bounds.trailing.constraint(equalTo: state.containerBounds.trailing)
				leading.priority = .userLow
				leading2.priority = .userHigh
				trailing.priority = .required
				leading.isActive = true
				leading2.isActive = true
				trailing.isActive = true
				state.storage.constraints.append(leading)
				state.storage.constraints.append(leading2)
				state.storage.constraints.append(trailing)
			case .center:
				let center = bounds.centerX.constraint(equalTo: state.containerBounds.centerX)
				center.priority = .required
				center.isActive = true
				state.storage.constraints.append(center)
				let width = bounds.width.constraint(equalTo: state.containerBounds.width)
				width.priority = .userLow
				width.isActive = true
				state.storage.constraints.append(width)
			case .fill:
				let leading = bounds.leading.constraint(equalTo: state.containerBounds.leading)
				let trailing = bounds.trailing.constraint(equalTo: state.containerBounds.trailing)
				leading.priority = .userHigh
				trailing.priority = .userHigh
				leading.isActive = true
				trailing.isActive = true
				state.storage.constraints.append(leading)
				state.storage.constraints.append(trailing)
			}
			
			state.containerBounds.top = bounds.bottom
		}
	}
	
	@discardableResult
	fileprivate func layout(entity: Entity, state: inout State, needDimensionAnchor: Bool = false) -> NSLayoutDimension? {
		switch entity.content {
		case .space(let dimension):
			if let d = state.dimension, (d.ratio != 0 || d.constant != 0) {
				let box = Layout.Box()
				state.view.addLayoutBox(box)
				state.storage.boxes.append(box)
				constrain(bounds: Bounds(box: box), leading: Dimension(), length: d, breadth: nil, relative: false, state: &state)
				state.previousEntityBounds = nil
			}
			if dimension.ratio != 0 || needDimensionAnchor {
				let box = Layout.Box()
				state.view.addLayoutBox(box)
				state.storage.boxes.append(box)
				constrain(bounds: Bounds(box: box), leading: Dimension(), length: dimension, breadth: nil, relative: false, state: &state)
				return axis == .horizontal ? box.widthAnchor : box.heightAnchor
			}
			state.dimension = dimension
			return nil
		case .layout(let l, let size):
			let box = Layout.Box()
			state.view.addLayoutBox(box)
			state.storage.boxes.append(box)
			let bounds = Bounds(box: box)
			l.add(to: state.view, containerBounds: bounds, storage: state.storage)
			constrain(bounds: bounds, leading: state.dimension ?? Dimension(), length: size?.length, breadth: size?.breadth, relative: size?.relative ?? false, state: &state)
			state.dimension = nil
			state.previousEntityBounds = bounds
			return needDimensionAnchor ? (axis == .horizontal ? box.widthAnchor : box.heightAnchor) : nil
		case .matched(let first, let pairs, let priority):
			if needDimensionAnchor {
				let box = Layout.Box()
				state.view.addLayoutBox(box)
				state.storage.boxes.append(box)
				var subState = State(containerBounds: state.containerBounds, in: state.view, storage: state.storage)
				layout(entity: entity, state: &subState)
				state.dimension = nil
				state.previousEntityBounds = Bounds(box: box)
				return axis == .horizontal ? box.widthAnchor : box.heightAnchor
			} else {
				let first = layout(entity: first, state: &state, needDimensionAnchor: true)!
				for p in pairs {
					layout(entity: p.independent, state: &state)
					let match = layout(entity: p.same, state: &state, needDimensionAnchor: true)!
					let constraint = match.constraint(equalTo: first)
					state.storage.constraints.append(constraint)
					constraint.priority = priority
					constraint.isActive = true
				}
				return nil
			}
		case .sizedView(let v, let size):
			let view = v.viewInstance
			view.translatesAutoresizingMaskIntoConstraints = false
			state.view.addSubview(view)
			constrain(bounds: Bounds(view: view, marginEdges: .none), leading: state.dimension ?? Dimension(), length: size?.length, breadth: size?.breadth, relative: size?.relative ?? false, state: &state)
			state.dimension = nil
			state.previousEntityBounds = Bounds(view: view, marginEdges: .none)
			return needDimensionAnchor ? (axis == .horizontal ? view.widthAnchor : view.heightAnchor) : nil
		}
	}
	
	fileprivate func add(to view: Layout.View, containerBounds: Bounds, storage: Storage) {
		var state = State(containerBounds: containerBounds, in: view, storage: storage)
		for entity in entities {
			layout(entity: entity, state: &state)
		}
		if let previous = state.previousEntityBounds {
			switch axis {
			case .horizontal:
				let trailingAnchor = previous.trailing
				let boundsTrailingAnchor = state.containerBounds.trailing
				let trailingConstraint: NSLayoutConstraint
				let trailing = state.dimension ?? Dimension()
				
				// NOTE: we must invert the relationship since we're laying out backwards
				switch trailing.relationship {
				case .equal: trailingConstraint = trailingAnchor.constraint(equalTo: boundsTrailingAnchor, constant: -trailing.constant)
				case .lessThanOrEqual: trailingConstraint = trailingAnchor.constraint(greaterThanOrEqualTo: boundsTrailingAnchor, constant: -trailing.constant)
				case .greaterThanOrEqual: trailingConstraint = trailingAnchor.constraint(lessThanOrEqualTo: boundsTrailingAnchor, constant: -trailing.constant)
				}
				
				trailingConstraint.priority = trailing.priority
				state.storage.constraints.append(trailingConstraint)
				trailingConstraint.isActive = true
			case .vertical:
				let trailingAnchor = previous.bottom
				let boundsTrailingAnchor = state.containerBounds.bottom
				let trailingConstraint: NSLayoutConstraint
				let trailing = state.dimension ?? Dimension()
				
				// NOTE: we must invert the relationship since we're laying out backwards
				switch trailing.relationship {
				case .equal: trailingConstraint = trailingAnchor.constraint(equalTo: boundsTrailingAnchor, constant: -trailing.constant)
				case .lessThanOrEqual: trailingConstraint = trailingAnchor.constraint(greaterThanOrEqualTo: boundsTrailingAnchor, constant: -trailing.constant)
				case .greaterThanOrEqual: trailingConstraint = trailingAnchor.constraint(lessThanOrEqualTo: boundsTrailingAnchor, constant: -trailing.constant)
				}
				
				trailingConstraint.priority = trailing.priority
				state.storage.constraints.append(trailingConstraint)
				trailingConstraint.isActive = true
			}
		}
	}
}

// NOTE:
//
// Views often have their own intrinsic size, and they maintain this size at
// either the `.defaultLow` or `.defaultHigh` priority. Unfortunately, layout
// doesn't work well if this intrinsic priority is perfectly balanced with the
// user-applied layout priority.
//
// For this reason, CwlLayout defaults to using the following layout priorities
// which are scaled to be slightly different to the default priorities. This
// allows you to easily set layout priorities above, between or below the
// intrinisic priorities without always resorting to `.required`.
//
extension Layout.Dimension.Priority {
	#if os(macOS)
		#if swift(>=4)
			static let userLow = NSLayoutConstraint.Priority(rawValue: NSLayoutConstraint.Priority.defaultLow.rawValue * 0.875)
			static let userMid = NSLayoutConstraint.Priority(rawValue: NSLayoutConstraint.Priority.required.rawValue * 0.5)
			static let userHigh = NSLayoutConstraint.Priority(rawValue: NSLayoutConstraint.Priority.defaultHigh.rawValue * 1.125)
		#else
			static let userLow = NSLayoutPriorityDefaultLow * 0.875
			static let userMid = NSLayoutPriorityRequired * 0.5
			static let userHigh = NSLayoutPriorityDefaultHigh * 1.125
		#endif
	#else
		#if swift(>=4)
			static let userLow = UILayoutPriority(rawValue: UILayoutPriority.defaultLow.rawValue * 0.875)
			static let userMid = UILayoutPriority(rawValue: UILayoutPriority.required.rawValue * 0.5)
			static let userHigh = UILayoutPriority(rawValue: UILayoutPriority.defaultHigh.rawValue * 1.125)
		#else
			static let userLow = UILayoutPriorityDefaultLow * 0.875
			static let userMid = UILayoutPriorityRequired * 0.5
			static let userHigh = UILayoutPriorityDefaultHigh * 1.125
		#endif
	#endif
}

extension Layout.View {
	// DEBUGGING TIP:
	// As of Xcode 8, the "Debug View Hierarchy" option does not show layout guides, making debugging of constraints involving layout guides tricky. To aid debugging in these cases, set the following condition to `true && DEBUG` and CwlLayout will create views instead of layout guides.
	// Otherwise, you can set this to `false && DEBUG`.
	#if true && DEBUG
		fileprivate func addLayoutBox(_ layoutBox: Layout.Box) {
			layoutBox.translatesAutoresizingMaskIntoConstraints = false
			self.addSubview(layoutBox)
		}
		fileprivate func removeLayoutBox(_ layoutBox: Layout.Box) {
			layoutBox.removeFromSuperview()
		}
	#else
		fileprivate func addLayoutBox(_ layoutBox: Layout.Box) {
			self.addLayoutGuide(layoutBox)
		}
		fileprivate func removeLayoutBox(_ layoutBox: Layout.Box) {
			self.removeLayoutGuide(layoutBox)
		}
	#endif
}

fileprivate var associatedLayoutKey = NSObject()
fileprivate func setLayout(_ newValue: Layout.Storage?, for object: Layout.View) {
	objc_setAssociatedObject(object, &associatedLayoutKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
}
fileprivate func getLayout(for view: Layout.View) -> Layout.Storage? {
	return objc_getAssociatedObject(view, &associatedLayoutKey) as? Layout.Storage
}

fileprivate extension Layout.View {
	func remove(constraintsAndBoxes previousLayout: Layout.Storage?, subviews: Set<Layout.View>) {
		guard let previous = previousLayout else { return }
		for constraint in previous.constraints {
			constraint.isActive = false
		}
		for box in previous.boxes {
			self.removeLayoutBox(box)
		}
		subviews.forEach { $0.removeFromSuperview() }
	}
}

fileprivate func applyLayoutToView(view: Layout.View, params: (layout: Layout, bounds: Layout.Bounds)?) {
	var removedViews = Set<Layout.View>()
	
	// Check for a previous layout and get the old views
	let previous = getLayout(for: view)
	previous?.layout.forEachView { view in removedViews.insert(view) }
	
	guard let (layout, bounds) = params else {
		// If there's no new layout, remove the old layout and we're done
		view.remove(constraintsAndBoxes: previous, subviews: removedViews)
		return
	}
	
	// Check if this will be animated
	let shouldAnimate = layout.animate != .none && (previous != nil || layout.animate != .subsequent)
	
	// Exclude views in the new layout from the removed set. If we're animating, we'll need animated and added sets too.
	var animatedViews = Set<Layout.View>()
	var addedViews = Set<Layout.View>()
	layout.forEachView { v in
		if let animated = removedViews.remove(v), shouldAnimate {
			animatedViews.insert(animated)
		} else if shouldAnimate {
			addedViews.insert(v)
		}
	}
	
	// Now that we know the precise removed set, remove them.
	if shouldAnimate && addedViews.count == 0 && removedViews.count > 0 {
		// If we're animating the removal of views but not the insertion of views, animate this removal
		UIView.transition(with: view, duration: 0.2, options: [.transitionCrossDissolve, .allowUserInteraction], animations: {
			view.remove(constraintsAndBoxes: previous, subviews: removedViews)
		}, completion: { completed in })
	} else {
		view.remove(constraintsAndBoxes: previous, subviews: removedViews)
	}
	
	// Apply the new layout
	let storage = Layout.Storage(layout: layout)
	layout.add(to: view, containerBounds: bounds, storage: storage)
	
	// If we're not animating, store the layout and we're done.
	if !shouldAnimate {
		setLayout(storage, for: view)
		return
	}
	
	if addedViews.count > 0 {
		// Apply the layout, so new views have a precise size
		view.layoutIfNeeded()
		
		// Remove the new views and revert to the old layout
		view.remove(constraintsAndBoxes: storage, subviews: addedViews)
		if let p = previous {
			let oldStorage = Layout.Storage(layout: layout)
			p.layout.add(to: view, containerBounds: bounds, storage: oldStorage)

			// Immediately remove the old constraints but keep the old views
			view.remove(constraintsAndBoxes: oldStorage, subviews: [])
		}
		
		// Animate the simultaneous removal and addition of new views
		UIView.transition(with: view, duration: 0.2, options: [.transitionCrossDissolve, .allowUserInteraction], animations: {
			removedViews.forEach { $0.removeFromSuperview() }
			addedViews.forEach { view.addSubview($0) }
		}, completion: { completed in })
		
		// Reapply the new layout. Since the new views are already in-place
		let reapplyStorage = Layout.Storage(layout: layout)
		layout.add(to: view, containerBounds: bounds, storage: reapplyStorage)
		setLayout(reapplyStorage, for: view)
	} else {
		setLayout(storage, for: view)
	}
	
	// Animate the frames of the new layout
	UIView.animate(withDuration: 0.2, delay: 0, options: [.allowUserInteraction], animations: {
		view.layoutIfNeeded()
	}, completion: { completed in })
}
